Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Obsługa błędów w PDO
Forum PHP.pl > Forum > PHP
nowy_pehapowiec
Muszę się Was poradzić, jakiej obsługi błędów używacie?

Ja używam: $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); zaraz po zdefiniowaniu połączenia.
Czy jest jakiś lepszy sposób. Może z dokładniejszymi opisami błędów?


pozdro
erix
Łapanie wyjątków, to chyba najlepszy z dostępnych sposobów obsługi błędów dostępnych w PHP. Nie musisz zawsze sprawdzać if(!...), tylko wrzucasz w blok try i łapiesz jak trzeba, bez zagnieżdżania setek struktur kontrolnych.

Cytat
Może z dokładniejszymi opisami błędów?

One są i tak wystarczająco wyczerpujące. ;] Poza tym, komunikaty błędów bazy są identyczne we wszystkich sterownikach, gdyż ich treść zwraca biblioteka kliencka, a nie akurat PDO. PDO jest tylko front-endem dla biblioteki DBMS (w przypadku MySQL - libmysql) i jeśli chciałbyś dokładniejszych opisów błędów - musiałbyś się nią zająć, a nie PDO.

edit@down pewnie pokazane palcem, co konkretnie napisać, aby było ok, albo generowanie nowego, poprawnego zapytania. biggrin.gif
nospor
Cytat
jeśli chciałbyś dokładniejszych opisów błędów - musiałbyś się nią zająć, a nie PDO.
No ale pytanie: co tam można jeszcze dokładniej podawać? winksmiley.jpg
fander
Cytat(nospor @ 23.09.2009, 11:58:47 ) *
No ale pytanie: co tam można jeszcze dokładniej podawać? winksmiley.jpg


http://pl.php.net/manual/en/pdo.constants.php

Masz wszystkie stałe pre definiowane.
nospor
no ok, ale jak to ma się do pytania? Chodzilo o komunikat bledu a nie jakies parametry PDO winksmiley.jpg

Cytat
pewnie pokazane palcem, co konkretnie napisać, aby było ok, albo generowanie nowego, poprawnego zapytania.
I to jest myśl winksmiley.jpg
fander
w takim razie niech kolega filtruje i używa PDOException class http://pl.php.net/manual/en/class.pdoexception.php , btw tu chodzi o obsługę błędów?
nospor
no przeciez uzywa wlasnie wyjatkow. w pytaniu chodzilo czy jest cos lepszego. Odpowiedź juz padla...

No a moje pytanie :
Cytat
No ale pytanie: co tam można jeszcze dokładniej podawać?
bylo pytaniem retorycznym
nowy_pehapowiec
dzięki za wszystkie odp

Trocha nieściśle się wyraziłem. Chodziło mi może nie tyle co o obsługę błędów w pełnym zakresie (z wyjątkami) właśnie o komunikaty o błędach. Na razie ważne dla mnie jest czy był jakiś błąd i jaki. No i: $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); mi to zapewnia. Czy używając try-catch dostane coś więcej? erix pisał, że komunikaty błędów są takie same. Co więc dostaje z używania try? Jaki w nim bonus siedzi. Ale tak w praktyce, nie w teorii:)

pozdro
Crozin
A wiesz w ogóle jak działają wyjątki?
nowy_pehapowiec
Powiem, szczerze że próbowałem się przez nie przebić ale nie zajarzyłem o co w nich bangla :| :\
Crozin mógłbyś coś napisać o tym jakieś 2 albo 3 zdania? Tak w celu pouczenia mniej zaawansowanego kolegi?


pozdro
Riklaunim
W innych bardziej spójnych pod tym względem językach wyjątek jest rzucany gdy aplikacja nie może działać poprawnie - np. baza nieosiągalna, błąd w zapytaniu SQL itd. PDO dokładnie w ten sposób wykorzystuje wyjątki. Jeżeli coś jest nie tak to rzucony jest wyjątek, który powinien zostać przechwycony, działanie kodu zakończone, a wyjątek gdzieś zapisany dla programisty winksmiley.jpg (a userowi wyświetlony komunikat że coś się popsuło).
nowy_pehapowiec
Nie do końca jarzę o co bangla z tymi wyjątkami.

Skrypt jest wykonywany i natrafia na błąd i przerywa wykonywanie. Np brak domknięcia nawiasu albo błąd w zapytaniu sql albo odwołanie się do czegoś co nie istnieje.
I teraz wyświetla mi się błąd na ekranie, że w którejś linijce coś sknociłem. I to mam dzięki konfiguracji błędów w php.ini i dzięki:
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

No to co jeszcze mogę osiągnąć? Co to jest ten wyjątek no za cholerę nie jarzę.

pozdro
dr_bonzo
pseudokod
Kod
try
{
    zaloguj_usera();
    pobierz_newsy();
    zapisz_statystyki_w_bazie();
    pobierz_z_bazy_x();
    zapisz_w_bazie_a();
    zapisz_w_bazie_a();
    .............
    zapisz_w_bazie_z();

}
catch ( PDOException $e )
{
    // jesli cokolwiek wyzej sie nie wykona - bo np. masz bledne dane do inserta
    // to skrypt OD razu przeskoczy tutaj
       zaloguj wyjatek($e);
       pokaz_userowi_ze_strona_padla();
}


No i sproboj to zapisac bez uzycia wyjatkow, tak zebys sprawdzal kazda operacje, a w przypadku niepowodzenia pokazal ekran bledu:

Kod
if ( ! zaloguj_usera() )
{
    handleError();
}
if ( ! pobierz_newsy() )
{
    handleError();
}
.....
// tu powinienes dostac ku***cy
nospor
przesadzacie...
Pewnie mnie zlinczujecie ale...
ja nie używam wyjątków (znaczy sporadycznie używam). Nie używam ich też przy PDO. Nie lubię tego shitu gdy jest nadużywany.
Błąd wczytywania newsow? ok, newsy sie nie wyswietlają, do logow idzie mi wpis o bledzie zapytania, user nie widzi wpisów.
błąd zalogowania? ok, user widzi info ze blad, do logow idzie info ze blad, kur##@$ nie dostaje.

Może to kwesta przyzwyczajenia. ale ku#$#4 dostaje jak widze jak ktoś pisze ze jak sie nie uzywa wyjątków to mozna ku#$#@ dostac winksmiley.jpg
erix
Cytat
Nie lubię tego shitu gdy jest nadużywany.

No nie przesadzaj; nie lubisz, gdy się nadużywa if? Wyjątki, to też struktura kontrolna.

Cytat
dostaje jak widze jak ktoś pisze ze jak sie nie uzywa wyjątków to mozna ku#$#@ dostac

A ja dostaję k@#(*$&, gdy widuję coś takiego:

  1. if(zapiszdane1()){
  2. if(zapiszdane2()){
  3. if(zapiszdane3()){
  4. if(zapiszdane4()){
  5. echo 'wszystko ok!';
  6. }else{
  7. die('blad');
  8. }
  9. }else{
  10. die('blad');
  11. }
  12. }else{
  13. die('blad');
  14. }
  15. }else{
  16. die('blad');
  17. }


Skoro można wszystko pięknie ładnie napisać w takiej postaci:
  1. try{
  2. zapiszdane1();
  3. zapiszdane2();
  4. zapiszdane3();
  5. zapiszdane4();
  6. }catch(Exception $ex){
  7. die('blad');
  8. }
Riklaunim
Cytat(nospor @ 25.09.2009, 10:15:53 ) *
Może to kwesta przyzwyczajenia. ale ku#$#4 dostaje jak widze jak ktoś pisze ze jak sie nie uzywa wyjątków to mozna ku#$#@ dostac winksmiley.jpg

hehe ;] Zależy jak zrobisz obsługę błędów. Jak będzie działa to jest dobra i tyle. Gorzej jak rzuci się coś nieprzewidzianego, co nie podpadnie pod system logowania błędów.
nospor
Cytat
if(zapiszdane1()){
if(zapiszdane2()){
if(zapiszdane3()){
if(zapiszdane4()){
echo 'wszystko ok!';
}else{
die('blad');
}
}else{
die('blad');
}
}else{
die('blad');
}
}else{
die('blad');
}
kurcze.... to ze nie uzywam wyjątków nie znaczy ze piszę tak jak tu pokazałeś. Jak widze taki kod to też załamki dostaje.

Cytat
. Gorzej jak rzuci się coś nieprzewidzianego, co nie podpadnie pod system logowania błędów.
Pod system logowania błędów wchodzi każdy błąd.
erix
Cytat
kurcze.... to ze nie uzywam wyjątków nie znaczy ze piszę tak jak tu pokazałeś.

Nie to miałem na myśli. Po prostu takie skrajne sytuacje wymagają odpowiedniej kontroli. Czasem zachodzi potrzeba wykonywania paru operacji ciurkiem, takiej pseudo-transakcji po stronie skryptu i zamiast klepać kilka(naście?) ifów lepiej wszystko oprzeć o wyjątki.

Cytat
Jak widze taki kod to też załamki dostaje.

Uwierz, często coś takiego widuję. tongue.gif
nospor
Cytat
Uwierz, często coś takiego widuję
Ale to jest wina programisty a nie techniki. Owszem, wyjątki mogą zmniejszyć ryzyko takich kodów ale kiepski programista i na wyjątkach ci zrobi taką kaszane ze wymiękniesz.

Miałem sporą styczność z wyjątkami w javie. być może miałem pecha bo musiałem korzystać z libów napisanych poprostu "cudnie" i niesamowicie się zraziłem do wyjątków.

Nie mówię że wyjątki są be. Mówię jedynie by nie pisać:
Cytat
// tu powinienes dostac ku***cy

bo to ma się dla skrajnych przypadków.
dr_bonzo
Ojej, moze przesadzilem z ku***ca smile.gif

Ale wyjatki pozwalaja oddzielic normalny kod akcji (wewnatrz try{}) od czesci do obslugi bledow (catch{}).
Zamiast miec lasu ifow() po prostu wykonuje operacje, a bledy obsluguje "na dole".

  1. public function _update($id = null)
  2. {
  3. try
  4. {
  5. $product = Product::find($id);
  6. $data = $this->params->get('product');
  7. $data['discount_limit'] = $data->getFloat('discount_limit') / 100.0; // 13.2% => 0.132
  8.  
  9. $oldProfile = $product->getProfile();
  10. $oldOptionGroupID = $product->option_group_id;
  11. $product->setAll($data);
  12. $this->tryToCreateProducer($product); // ! after setAll() to overwrite producer_id
  13. $product->save();
  14.  
  15. // categories
  16. $oldIDs = (array)$data->get('category_id')->get('old')->getAll();
  17. $newIDs = (array)$data->get('category_id')->get('new')->getAll();
  18. $product->updateCategoryAssignment( $oldIDs, $newIDs );
  19.  
  20. // profile
  21. $newProfile = $product->getProfile();
  22. $this->setUpProfile($product, $this->form('product_field'), $oldProfile, $newProfile);
  23.  
  24. // options/variants
  25. $oldVariantsData = $this->params['variant']['old'];
  26. $newVariantsData = $this->params['variant']['new'];
  27. $newOptionGroupID = $product->option_group_id;
  28. $this->setUpVariants($product, $newVariantsData, $oldVariantsData, $newOptionGroupID, $oldOptionGroupID );
  29.  
  30. // index..
  31. $this->refreshProductNiceURLs($product);
  32. $this->reindexProduct($product);
  33. }
  34. catch ( DAO_ValidationException $e)
  35. {
  36. // tu pokaze ponownie ekran edycji produktu jesli w ktorymkolwiek miejscu produkt zostal nieprawidlowo wypelniony
  37. // danymi przez usera, a to moze byc kilka poziomow glebiej w poziomie wywolan metod (IF-hell jesli by to robic bez wyjatkow
  38. // ktore same "wyskakuja" w gore stosu wywolania
  39. // no i nie moge tu logowac bledow
  40. $this->view->product = $product;
  41. $this->renderAction('edit.tpl', 'product/tpl_admin/product_popup.tpl');
  42. }
  43. }
nospor
Cytat
Ale wyjatki pozwalaja oddzielic normalny kod akcji (wewnatrz try{}) od czesci do obslugi bledow (catch{}).
Ale ja tego nie neguje a nawet się z tym zgadzam smile.gif

No teraz inny kod:
  1. try
  2. {
  3. $product = Product::find($id);
  4.  
  5. $oldProfile = $product->getProfile();
  6.  
  7. $newProfile = $product->getProfile();
  8.  
  9. }
  10. catch ( DAO_ValidationException $e)
  11. {
  12. }

No i super. Tylko w tym momencie nie wiesz co wywolalo wyjątek. Czy to find, czy to getProfile dla oldProfie czy tez moze dla newProfile.
Zeby sie dowiedziec to find czy tez getProfile musi rzucac innym wyjątkiem. Juz wiec raz ze musisz zdefiniowac te wyjątki, dwa ze zaczyna ci rosnąc blok catchow.
No i znowu jednak nie bedziesz wiedzial czy to bylo oldProfile czy newProfile. Trzeba dodac parę ifow. Ostateczne sprawdzanie zaczyna wiec rosnąć w kod. nie zmienia to jednak faktu, ze jest prawdą to co mowiles: sprawdzanie oddzielilismy od logiki.

  1. try
  2. {
  3. $product = Product::find($id);
  4.  
  5. $oldProfile = $product->getProfile();
  6.  
  7. $newProfile = $product->getProfile();
  8.  
  9. }
  10. catch ( DAO_ValidationException $e)
  11. {
  12. }
  13. catch ( FindException $e)
  14. {
  15. }
  16. catch ( getProfile $e)
  17. {
  18. if (oldprofile)...
  19. if (newProfile)
  20. }


Oczywiscie moze nas nic nie obchodzic co wywołało wyjątek - grunt ze sie pojawił i jest źle. Co go wywołało to se kiedys w logach poszukamy.
erix
Cytat
No i super. Tylko w tym momencie nie wiesz co wywolalo wyjątek.

http://pl2.php.net/manual/pl/language.exce...s.extending.php - final public function getTrace(); // an array of the backtrace() ;]

To tak ogólnie.

Cytat
Trzeba dodac parę ifow. Ostateczne sprawdzanie zaczyna wiec rosnąć w kod. nie zmienia to jednak faktu, ze jest prawdą to co mowiles: sprawdzanie oddzielilismy od logiki.

Zależy, jak plujesz + to, co zacytowałem.
nospor
Cytat
http://pl2.php.net/manual/pl/language.exce...s.extending.php - final public function getTrace(); // an array of the backtrace()
Nie o to mi chodzilo. To ze w logowaniu bledow bedziesz wiedzial co go wywolalo to oczywista sprawa. Ale chyba nie bedziesz w catchu analizowal sciezki bledu...
erix
No nie, ale zawsze pozostaje kwestia konstrukcji wyjątków - możesz przecież przeciążyć konstruktor i pluć własnym wyjątkiem - co dalej zrobisz - Twoja wola. winksmiley.jpg
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.