Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [MySQL][PHP]Poprawność funkcji łączących z bazą, Prośba o schematowe "dobre rady".
ixpack
post
Post #1





Grupa: Zarejestrowani
Postów: 248
Pomógł: 55
Dołączył: 1.06.2010
Skąd: mam to wiedzieć?

Ostrzeżenie: (0%)
-----


Proszę kogoś elokwentnego o pomoc w poprawieniu niżej podanych funkcji (mój 1szy wątek i trochę się boję "was", ale musi być kiedyś ten 1szy raz (IMG:style_emoticons/default/winksmiley.jpg) ):

  1. function polaczenie()
  2. {
  3. $wynik = @new mysqli('ip.ip.ip.ip', 'login', 'haslo', 'baza');
  4. if (!$wynik) throw new Exception('Error with connection, please try later');
  5. else $wynik->autocommit(TRUE);
  6. return $wynik;
  7. }


To jedna z 2ch funkcji - ustanawiająca połączenie... Co powinienem w niej zmienić?

  1. function pobierz_nazwe_czegos($idczegos)
  2. {
  3. $idczegos = intval($idczegos);
  4. $lacz = polaczenie();
  5. $zapytanie = "select nazweczegos from tabelaczegos where idczegos = $idczegos";
  6. $wynik = @$lacz->query($zapytanie);
  7. if (!$wynik)
  8. return false;
  9. $ilosc_nazw = @$wynik->num_rows;
  10. if ($ilosc_nazw == 0)
  11. return false;
  12. $nazwa = $wynik->fetch_object();
  13. $lacz->close();
  14. return $nazwa->nazwaczegos;
  15. }
  16.  
  17. $nazwa = pobierz_nazwe_czegos($idczegos);





Tu pobieram tylko jedną nazwę elementu, gdzie znam konkretny id elementu - Jestem "samoukiem", gdzieś czytałem, gdzieś podpatrzyłem, sam napisałem... Dlatego "pytam", bo chyba sam lepiej nie wymyślę.

Ps. Czy muszę zamykać połączenie "$lacz->close();" jeżeli w funkcji 1 mam "autocommit(TRUE);"?

Dzięki za odpowiedź (IMG:style_emoticons/default/smile.gif)


ixpack
-------------
Łatwo jest być odważnym za murami własnego zamku...
Go to the top of the page
+Quote Post
thek
post
Post #2





Grupa: Moderatorzy
Postów: 4 362
Pomógł: 714
Dołączył: 12.02.2009
Skąd: Jak się położę tak leżę :D




Jeśli stosujesz wyjątki to zrób coś z @ i ich usunięciem. Poza tym rzucasz wyjątki, ale nigdzie nie widzę ich przechwytywania (nie widzę bloków try-catch). Strzelasz nimi na wiwat chyba (IMG:style_emoticons/default/winksmiley.jpg)

Co do zamykania połączenia to świadczy to raczej o samym programiście i jego podejściu do "czystości". PHP sam zamknie połączenia gdy skrypt się skończy lub zrobi to najpóźniej przy okazji zwalniania pamięci przez Garbage Collector. Tak więc to bardziej dobre zalecenie niż konieczność.
Go to the top of the page
+Quote Post
zend
post
Post #3





Grupa: Zarejestrowani
Postów: 580
Pomógł: 85
Dołączył: 25.03.2010
Skąd: Skrzyszów :)

Ostrzeżenie: (0%)
-----


Jak myślisz, co się stanie gdy wywołam polaczenie(); polaczenie(); polaczenie();? Do dobrym pomysłem było by przekazanie do wyjątku kodu błędu i samego błędu, ponieważ przy różnych błędach będziesz miał ten sam komunikat, co wcale nie ułatwi debugowania, potem w aplikacji produkcyjnej błędy można wygasić i wyświetlić zamiast nich jakieś przyjaźniejsze komunikaty
  1. $wynik = $lacz->query($zapytanie); //w przypadku niepowodzenia tu powinien być wyjątek a nie return false;
Go to the top of the page
+Quote Post
ixpack
post
Post #4





Grupa: Zarejestrowani
Postów: 248
Pomógł: 55
Dołączył: 1.06.2010
Skąd: mam to wiedzieć?

Ostrzeżenie: (0%)
-----


Nie wiem, czy dobrze przejrzałem manual, ale czy to wygląda lepiej?:

  1. function lacz_bd()
  2. {
  3. $wynik = new mysqli('ip.ip.ip.ip', 'login', 'pass', 'baza');
  4. if (!$wynik)
  5. throw new Exception(' no 1');
  6. else
  7. {
  8. $wynik->autocommit(TRUE);
  9. return $wynik;
  10. }
  11. }
  12.  
  13. function pobierz_nazwe_czegos($idczegos)
  14. {
  15. $idczegos = intval($idczegos);
  16. $lacz = polaczenie();
  17. $zapytanie = "select nazweczegos from tabelaczegos where idczegos = $idczegos";
  18. $wynik = $lacz->query($zapytanie);
  19. if (!$wynik)
  20. throw new Exception(' no 2');
  21. else
  22. {
  23. $ilosc_nazw = $wynik->num_rows;
  24. if ($ilosc_nazw == 0) return false;
  25. $nazwa = $wynik->fetch_object();
  26. $lacz->close();
  27. return $nazwa->nazwaczegos;
  28. }
  29. }
  30.  
  31. try
  32. {
  33. $nazwa = pobierz_nazwe_czegos($idczegos);
  34. }
  35. catch (Exception $e)
  36. {
  37. echo 'Error: ', $e->getMessage(), "\n";
  38. }


I tu nasuwa się kolejne pytanie (IMG:style_emoticons/default/smile.gif) : Jak odbije się wstawienie całego skryptu w blok "try" na działanie i szybkość strony? Czy powinienem członkować kod i odpowiednie "kawałki" wstawiać w kolejne bloki "try" i czy powinienem nadawać inne zmienne ($e, $f itd.)?

Ten post edytował ixpack 1.06.2010, 13:05:29
Go to the top of the page
+Quote Post
zend
post
Post #5





Grupa: Zarejestrowani
Postów: 580
Pomógł: 85
Dołączył: 25.03.2010
Skąd: Skrzyszów :)

Ostrzeżenie: (0%)
-----


set exception handler - poczytaj także o tym. Sprawdź też jakie inne parametry przyjmuje klasa exception. Nadal każde pobranie połączenia do bazy powoduje nawiązanie kolejnego połączenia, mimo że połączenie mogło być już nawiązanie. Jeżeli mnie pamięć nie myli to w funkcji możesz skorzystać ze zmiennych statycznych, które mogą utrzymywać stan pomiędzy kolejnymi wywołaniami
Go to the top of the page
+Quote Post
ixpack
post
Post #6





Grupa: Zarejestrowani
Postów: 248
Pomógł: 55
Dołączył: 1.06.2010
Skąd: mam to wiedzieć?

Ostrzeżenie: (0%)
-----


Cytat(zend @ 1.06.2010, 14:22:01 ) *
set exception handler - poczytaj także o tym. Sprawdź też jakie inne parametry przyjmuje klasa exception. Nadal każde pobranie połączenia do bazy powoduje nawiązanie kolejnego połączenia, mimo że połączenie mogło być już nawiązanie. Jeżeli mnie pamięć nie myli to w funkcji możesz skorzystać ze zmiennych statycznych, które mogą utrzymywać stan pomiędzy kolejnymi wywołaniami


Ok, błędy błędami... Jeżeli chodzi o "static" - prosiłbym o lekkie wyjaśnienie, gdzie powinienem jej użyć? W funkcji polaczenie(); == lacz_db(); czy w funkcji pobierającej nazwę "static $lacz = polaczenie();" i ująć to w "if(!isset($lacz));"? Chyba tego nie rozumiem, ok rozumiem, że "static $zmienna;" w funkcji "x();" przekazuje swoją wartość do kolejnego wywołania funkcji "x();", ale jak to się ma do połączenia z bazą?

Funkcję "polaczenie();" używa na mojej stronie więcej funkcji... Do pobierania nazw i innych danych, zależnie od tego, czego akurat potrzebuję na stronie - i pytanie czy powinienem zmienić funkcję "polaczenie();", czy każdą inną funkcję z osobna, która wykorzystuje "polaczenie();" do łączenia się z bazą?

Co dzień poprawiam trochę kod, a kolejnego dnia widzę, że mam więcej i więcej poprawek do zrobienia (IMG:style_emoticons/default/biggrin.gif) .

Dziękuję za pomoc!
Go to the top of the page
+Quote Post
zend
post
Post #7





Grupa: Zarejestrowani
Postów: 580
Pomógł: 85
Dołączył: 25.03.2010
Skąd: Skrzyszów :)

Ostrzeżenie: (0%)
-----


Zmienną statyczną tworzysz w funkcji, jeżeli ta zmienna coś zawiera to zwracasz to, jeżeli nie, to przypisujesz połączenie od niej i zwracasz, modyfikacji wymaga jedynie funkcja polacz
  1. function polacz()
  2. {
  3. static $polaczenie;
  4.  
  5. if(is_resource($polaczenie))
  6. return $polaczenie;
  7.  
  8. echo 'laczy się';
  9. $polaczenie = opendir('./');
  10. return $polaczenie;
  11. }
  12.  
  13. polacz();
  14. polacz();
  15. polacz();
  16.  


Ten post edytował zend 2.06.2010, 10:18:22
Go to the top of the page
+Quote Post
ixpack
post
Post #8





Grupa: Zarejestrowani
Postów: 248
Pomógł: 55
Dołączył: 1.06.2010
Skąd: mam to wiedzieć?

Ostrzeżenie: (0%)
-----


  1. function polacz()
  2. {
  3. static $wynik;
  4.  
  5. if(is_resource($wynik)) return $wynik;
  6.  
  7. $wynik = new mysqli('ip.ip.ip.ip', 'login', 'pass', 'baza');
  8. if (!$wynik)
  9. throw new Exception(' no 1');
  10. else
  11. {
  12. $wynik->autocommit(TRUE);
  13. return $wynik;
  14. }
  15. }


@zend - ale po co tam opendir? Trochę to dla mnie zawiłe, bo jeżeli static przyjmuje "jakąś wartość", która jest przekazywana dalej... To i tak nawiązywane są nowe połączenia :/. Nie rozumiem tego - chyba jestem za głupi.
Go to the top of the page
+Quote Post
zend
post
Post #9





Grupa: Zarejestrowani
Postów: 580
Pomógł: 85
Dołączył: 25.03.2010
Skąd: Skrzyszów :)

Ostrzeżenie: (0%)
-----


Czemu opendir? Bo potrzebowałem coś co zwróci resource (IMG:style_emoticons/default/smile.gif) Wykonaj mój kod i powiedz ile razy się "połączy", a potem spróbuj bez statycznej zmiennej i sprawdź ile razy się połączy. Nawiązywanie kilku połączeń równoległych to strata zasobów i spowolnienie strony
Go to the top of the page
+Quote Post
ixpack
post
Post #10





Grupa: Zarejestrowani
Postów: 248
Pomógł: 55
Dołączył: 1.06.2010
Skąd: mam to wiedzieć?

Ostrzeżenie: (0%)
-----


Ok - zend to tak na zakończenie "moich" widzimisię (IMG:style_emoticons/default/smile.gif) ostatnie pytanko (nie tylko do zend):

Czy lepiej zostawić tak jak jest czyli (kilka funkcji, które łączą z kilkoma bazami danych, niektóre autocommit(true);, inne false) łączyć z bazami korzystając z funkcji wywołujących połączenie przez funkcje zadające pytania, czy może raz połączyć się z bazą na początku "strony", wykonać zapytania korzystając z funkcji, zamknąć połączenie?

Zdarza się, że skrypt wysyła około 2000 zapytań - oczywiście nie dla wszystkich zapytań otwierane są nowe połączenia w funkcjach pytających (IMG:style_emoticons/default/winksmiley.jpg) .

Ten post edytował ixpack 3.06.2010, 09:23:16
Go to the top of the page
+Quote Post
zend
post
Post #11





Grupa: Zarejestrowani
Postów: 580
Pomógł: 85
Dołączył: 25.03.2010
Skąd: Skrzyszów :)

Ostrzeżenie: (0%)
-----


Z tego co zrozumiałem to pytasz czy przekazywać połączenie jako parametr do funkcji czy wywoływać funkcję łączącą memnątrz ciała funkcji wykonującej zapytania. Przekazywanie jako paramert połączenia jest dobrą praktyką, pozwala zachować przejżystość kodu, ale w Twoim przypadku myślę że obie opcje będą dobre

Cytat
Zdarza się, że skrypt wysyła około 2000 zapytań
Zdaża się(IMG:style_emoticons/default/questionmark.gif) Takie rzeczy nie mogą się zdarzać! Jeśli program wysyła 20-30 zapytań to już jest dużo i wypadało by zoptymalizować, nie mówiąc już o tysiącach!

Ten post edytował zend 3.06.2010, 09:33:16
Go to the top of the page
+Quote Post
ixpack
post
Post #12





Grupa: Zarejestrowani
Postów: 248
Pomógł: 55
Dołączył: 1.06.2010
Skąd: mam to wiedzieć?

Ostrzeżenie: (0%)
-----


Ok okłamałem Cię - ilość zapytań dotyczy serwera współdzielonego, wszystkich zapytań jakie są zadawane bazom danych (MySQL Administrator), mój skrypt zadaje czasami około 200 zapytań



Zdarza się, gdy osobnik chce zobaczyć wszystkie produkty w katalogu - wówczas ilość produktów to PRODUKTY + (PRODUKTY * PODPRODUKTY) - mam wszystkich produktów i podproduktów około 2500, jednak w katalogu jest maksymalnie około 50 produktów + sprawdzenie dostępności podproduktów. I tak 50+(50*3) = 200, oczywiście nie każdy produkt ma 3 podprodukty, niektóre mają 0, inne 5. I stąd te ilości zapytań - skrypt musi sprawdzić, czy dany podprodukt jest dostępny czy nie.

Wiem, że muszę zoptymalizować to wszystko, na początku nie sądziłem, że tyle tego będzie... Będę musiał połączyć zapytania ale ciągle mam nowe pomysły bo zacząłem się jquery interesować (nieważne), Czy można połączyć zapytanie tak, aby pobrało informacje o produkcie z bazy x oraz kolejne informacje z bazy y?

Ten post edytował ixpack 3.06.2010, 09:51:51
Go to the top of the page
+Quote Post
zend
post
Post #13





Grupa: Zarejestrowani
Postów: 580
Pomógł: 85
Dołączył: 25.03.2010
Skąd: Skrzyszów :)

Ostrzeżenie: (0%)
-----


Nie, nie ma czegoś takiego jak złączenia pomiędzy bazami danych. Możesz zrobić złączenia pomiędzy tabelami. Przecież można to zamknąć w max 3 - 10 zapytaniach!
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 2.10.2025 - 07:43