Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [MySQL][PHP]Poprawność funkcji łączących z bazą
Forum PHP.pl > Forum > Przedszkole
ixpack
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 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ź smile.gif


ixpack
-------------
Łatwo jest być odważnym za murami własnego zamku...
thek
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 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ść.
zend
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;
ixpack
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 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.)?
zend
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
ixpack
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 biggrin.gif.

Dziękuję za pomoc!
zend
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.  
ixpack
  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.
zend
Czemu opendir? Bo potrzebowałem coś co zwróci resource 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
ixpack
Ok - zend to tak na zakończenie "moich" widzimisię 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 winksmiley.jpg.
zend
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ę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!
ixpack
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?
zend
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!
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.