Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: PDO + wyświetlanie błędów
Forum PHP.pl > Forum > PHP
WebCM
PDO oferuje 3 możliwości wyświetlania błędów:
- tryb cichy - brak komunikatów
- ostrzeżenia - Warning:
- wyjątki - Exception:

Która z nich jest najodpowiedniejsza do budowy aplikacji i wydajna? Aktualnie używam wyjątków. Przejdźmy do sytuacji, gdzie redaktor wysyła formularz z artykułem. Nie może go utracić w razie błędu!

W przypadku WYJĄTKÓW:
Kod
try { ... return 1; } catch(PDOException $e) { /*odeślij formularz z powrotem*/ }

Nie wystarczy zamknąć tylko PDO::commit() w instrukcji TRY, aby nie zatrzymywać wykonywania się skryptu, gdy wystąpi błąd. Dotyczy to nawet PDO::prepare - przynajmniej dla SQLite. W tym przypadku powodem mogą być pewnie literówki, nieznane funkcje, itd...

Gdy w try{} zamkniemy tylko commit(); - prawdopodobieństwo utraty danych z formularza jest raczej małe. Mimo tego należy rozważyć: brak kompatybilności SQLite / MySQL między wersjami, inne konfiguracje, czy nawet błąd w skrypcie?

Czy zastąpienie wyjątków wyjątków trybem cichym lub ostrzeżeniami (dla celów debuggingu) jest dobrym rozwiązaniem, czy jednak stanowi to potencjalną lukę w bezpieczeństwie? Nie chodzi tu o związki między zapytaniami (zapytanie X konieczne do wykonania zapytania Y), bo od tego są transakcje - mam rację? smile.gif
Kod
if( $db->commit() ) { ... return 1; } else { /* błąd - odeślij formularz użytkownikowi */ }

PS. Jeśli wyjątki są lepsze dla baz danych, podajcie konkretne argumenty przemawiające za nimi. smile.gif
nospor
Ja nie uzywam wyjatkow. Nie lubie tego ustrojstwa i juz smile.gif
PDO mi generuje warningi i mi to wystarcza. Jesli mam zaleznosci miedzy kolejnymi zapytaniami to biore to w tranzkacje. Jak ktores sie sypnie to rollback i po sprawie.
Sedziwoj
Cytat(nospor @ 18.03.2008, 12:03:28 ) *
Ja nie uzywam wyjatkow. Nie lubie tego ustrojstwa i juz smile.gif
PDO mi generuje warningi i mi to wystarcza. Jesli mam zaleznosci miedzy kolejnymi zapytaniami to biore to w tranzkacje. Jak ktores sie sypnie to rollback i po sprawie.


Tylko że czasem jak się sypnie na jednym to dzięki wyjątkowi możesz wyświetlić odpowiedni komunikat i coś z tym zrobić (np. wysłać sobie e-mail że się coś sypie), ale najważniejsze jest sterowaniem procesem wykonania, cały kod który ma się wykonać jest w jednym bloku try (pomijam transakcje, bo te to inny poziom obsługi przy błędach) i wykonanie odpowiedniej akcji na podstawie wyjątku.

Tylko że wszystko jest ładne w teorii, a z tego co miałem styczność z PDO, SOAP itp. to zawsze wychodzi, że jest za mało typów wyjątków, nie da się dojść co się dzieje, a też się zdarza, że nie ma wyjątku tylko zamiast obiektu zwraca '-1'...
carbolymer
@up: http://php.net.pl/manual/pl/function.set-error-handler.php tym możesz przejąć kontrolę nad warningami etc.

To zależy co jest lepsze. Jak dla mnie wyjątki, tylko musisz je odpowiednio przechwycić aby zapobiec utracie danych (zmniejszyć blok objęty try{} lub zbudować odpowiedni catch()).
Za wyjątkami: wygodny sposób przechwycenia błedu, przerwanie wykonywania kodu do końca
Za warningami: troche mniej wygodny sposób przechwytywania błędów niż z wyjątkami, ale kod jest wykonywany do końca (poza niektórymi errorami)
Za cichym: nikt nic nie będzie wiedział że coś nie zadziałało (minus: informację o tym czy wystąpił błąd bazy otrzymasz dopiero z wartości zwracanej funkcją)

To co będzie najlepsze to zależy od budowy twojej aplikacji i twoich upodobań.

Luk w bezpieczeństwie nie ma generalnie, zależy to od tego jak przechwycisz błąd.
nospor
Cytat
Tylko że czasem jak się sypnie na jednym to dzięki wyjątkowi możesz wyświetlić odpowiedni komunikat i coś z tym zrobić (np. wysłać sobie e-mail że się coś sypie),
Bez wyjatkow tez moge to zrobic, nie wiem w czym takim szczegolnym maja mi tu pomoc.

Nie bede ukrywal - jestem uprzedzony do wyjatkow. Zniechecila mnie do nich java, ktora jest jednym wielkim wyjatkiem. Normalnie przesadzili tam.
W php nie uzywam wyjatkow i nie mialem jeszcze sytuacji bym na tym jakos ucierpial.
WebCM
Są różne opinie. Wyjaśnię, o co mi właściwie chodzi. smile.gif Przykład: Fragment pliku - edycja sondy

Przejdźmy do $db->commit(). Czy baza danych zawsze wyrzuci błąd, gdy transakcja nie powiedzie się? Czy PDO zawsze automatycznie cofnie transakcję w przypadku błędu, czy trzeba użyć try{} catch(){}? Czy execute() i commit() zwracają FALSE, gdy rekord nie zostanie dodany - zarówno w SQLite i MySQL?

Z jednej strony do powiązane ze sobą zapytania powinno wykonywać się w transakcjach. Z drugiej można o tym zapomnieć. Czy wg Was należy przerywać wykonywanie skryptu PHP, gdy wystąpi błąd bazy danych i dlaczego? Właściwie prawdopodobieństwo wystąpienia błędu w dobrze napisanej aplikacji jest małe, ale chyba lepiej zabezpieczyć się? Przeglądarka nie zawsze zapamiętuje dane, jakie użytkownik wpisał do formularza, dlatego serwer powinien go odesłać z powrotem.

Try{} i catch{} przydaje się zawsze podczas tworzenia obiektu PDO. Wracając jednak do "ostrzeżeń": co w przypadku wyłączenia błędów na serwerze (gdy nawet error_reporting nie działa)?

PS. Jeszcze 1 sytuacja. Pobieramy dane (np. news, temat) z bazy. Gdy obejmiemy zapytanie instrukcją try{}catch{}, PDO nie wyrzuci błędu, gdy rekord nie istnieje. I tak musimy skorzystać z instrukcji warunkowej IF:
Kod
if( ! $news = $res -> fetch(2) ) return;
nospor
Cytat
Z drugiej można o tym zapomnieć. Czy wg Was należy przerywać wykonywanie skryptu PHP, gdy wystąpi błąd bazy danych i dlaczego?
Jedni przerywaja bo mowia ze skoro blad bazy znaczy ze bardzo źle i nalezy przerwac. Dla mnie to dziwne. Blad bledem ale ja strone i tak wyswietle smile.gif

Cytat
Wracając jednak do "ostrzeżeń": co w przypadku wyłączenia błędów na serwerze (gdy nawet error_reporting nie działa)?
Dla tego wlasnie error_reporting() mozna (nalezy) ustawic w skrypcie by jakis admin nie wylaczyl nam bledow
Sedziwoj
Cytat(carbolymer @ 18.03.2008, 18:39:40 ) *
@up: http://php.net.pl/manual/pl/function.set-error-handler.php tym możesz przejąć kontrolę nad warningami etc.


Nie wiem, może jestem głupi ale ono pozwala wyłapać "user-defined error" czyli tylko te co sam ustawiłeś, nie systemowe... (chyba że tu jest wyjątek i te zwracane są takowymi)

Cytat
To zależy co jest lepsze. Jak dla mnie wyjątki, tylko musisz je odpowiednio przechwycić aby zapobiec utracie danych (zmniejszyć blok objęty try{} lub zbudować odpowiedni catch()).
Za wyjątkami: wygodny sposób przechwycenia błedu, przerwanie wykonywania kodu do końca


Do końca? Jakiego końca, wiecie co ja nie wiem co pieprzycie, przecież wyjątki są po to aby uratować sytuację i wyświetlić coś zrozumiałego dla użytkownika oraz dla nas przekazać co jest nie tak.

Cytat(nospor @ 18.03.2008, 19:30:27 ) *
Bez wyjatkow tez moge to zrobic, nie wiem w czym takim szczegolnym maja mi tu pomoc.


W tym że powiedzą co i w jakiej kolejności to wywołało oraz wiesz w którym miejscu, dobry wyjątek mówi dlaczego wystąpił, backtrace mówi jak to się stało i gdzie szukać błęu.

Cytat
Nie bede ukrywal - jestem uprzedzony do wyjatkow. Zniechecila mnie do nich java, ktora jest jednym wielkim wyjatkiem. Normalnie przesadzili tam.
W php nie uzywam wyjatkow i nie mialem jeszcze sytuacji bym na tym jakos ucierpial.


Wiesz, są osoby co nie cierpią podejścia obiektowego, przecież też bez niego da się pisać, do tego wydajniej... Powiem tak spróbuj zrozumieć, jak już to zrobisz nie mówię abyś używał, bo mimo wszystko może się nie podobać, ale nie odrzucać czegoś czego się nie rozumie.

Cytat(nospor @ 18.03.2008, 20:13:38 ) *
Jedni przerywaja bo mowia ze skoro blad bazy znaczy ze bardzo źle i nalezy przerwac. Dla mnie to dziwne. Blad bledem ale ja strone i tak wyswietle


I właśnie po to są wyjątki, bo można jes banalnie prosto wyłapać i wiesz co się stało i co powiedzieć dalej, aby ostatecznie użytkownik dostał komunikat dla niego zrozumiały.

Cytat
Dla tego wlasnie error_reporting() mozna (nalezy) ustawic w skrypcie by jakis admin nie wylaczyl nam bledow


Tylko że jak zauważyłem że to łapie tylko błędy użytkownika (z tego co kiedyż testowałem tak było w rzeczywistości, więc wolę wyjątki) do tego w każdym miejscu można go obsłużyć indywidualnie, w zależności od kontekstu w jakim wystąpił. Oraz wiadomo co się stanie gdy... nie ma magicznego działania, a to ułatwia poznanie i modyfikację kodu.

Ja stosuję parę typów wyjątków, nie w sensie hierarchii, tylko znaczenia, są takie co pilnują aby obiekty były poprawianie używane i takie co mówią o błędach stricte niezależnych. Java wymusza ich obsługę co jest upierdliwe, ale jak się to robi to nic nie przemknie bokiem, chyba że ktoś nie przewidzi błędu na niższym poziomie. W PHP trzeba pilnować aby wyłapać te co mogą wystąpić w czasie pracy (bo mam ten drugi typ, co sprawdza dane które mogą być blednę tylko przy złym wykorzystaniu, ale też się przydają, jak się wykorzystuje coś wielokrotnie, pilnują tego co można zapomnieć)
nospor
Cytat
W tym że powiedzą co i w jakiej kolejności to wywołało oraz wiesz w którym miejscu, dobry wyjątek mówi dlaczego wystąpił, backtrace mówi jak to się stało i gdzie szukać błęu.
Ale ja to samo uzyskam bez wyjątkow. Nie wiem czy wiesz ale backtrace istnieje rowniez poza wyjatkami.

Cytat
I właśnie po to są wyjątki, bo można jes banalnie prosto wyłapać i wiesz co się stało i co powiedzieć dalej, aby ostatecznie użytkownik dostał komunikat dla niego zrozumiały.
Rownież to samo zrobie bez wyjatkow.

Ok, sa zwolennicy wyjatkow, sa zwolennicy niewyjatkow. Nie pisz mi tylko ze ich nie uzywam bo ich nie rozumiem. Tu sie mylisz - ja je rozumiem, ja ich poprostu nie trawie. Co innego gdyby wyjatki dawaly mi cos co potrzebuje a nie moge tego uzyskac bez nich. Ale to co potrzebuje i to co do tej pory wymieniles ja uzyskuje bez wyjatkow smile.gif

edit:
Cytat
Tylko że jak zauważyłem że to łapie tylko błędy użytkownika (z tego co kiedyż testowałem tak było w rzeczywistości, więc wolę wyjątki)
Mi tam lapie wszystko smile.gif

edit down: dobra, ja juz koncze bo tak mozem ciagnac w nieskonczonosc. smile.gif Ja i tak w php na wyjatki sie nie przesiade. A inni ktorzy sie wahają niech sami sobie wybiorą na podstawie tego tematu
Sedziwoj
Cytat(nospor @ 18.03.2008, 21:27:33 ) *
Ale ja to samo uzyskam bez wyjątkow. Nie wiem czy wiesz ale backtrace istnieje rowniez poza wyjatkami.


Wiem i pamiętam to. (ale to Twój argument więc Ci go zostawiłem biggrin.gif )

Cytat
Rownież to samo zrobie bez wyjatkow.


No właśnie nie, a raczej nie będzie to tak wygodne, błędy obsługujesz globalnie, a wyjątki lokalnie. A dzięki blokowi try catch nie masz kupy if'ów. Np. masz kawałek kodu który dodaje komentarz, obejmujesz go blokiem try i nie sprawdzasz czy połączenie z bazą działa, czy przy zapisie coś się kopie, nie masz tylko to co wykonuje dodawanie, czysty prosty kod, a co z błędami, no właśnie po to są bloki catch, a każdy może odpowiadać specyficznemu zdarzeniu i doskonale widzisz co będzie robione gdy nie uda się połączyć z bazą, co gdy nie uda się dodać krotki...
Właśnie główną zaletą jest przejrzystość kodu, bo po to właśnie piszemy obiektowo aby był bardziej zrozumiały.
A samo logowanie można zaszyć w klasie wyjątków i nie będzie też wykonane, ale też można będzie to zmienić w zależności od wyjątków, których typów dobrze napisanej aplikacji OOP masz dość sporo, ale dzięki temu są jednoznaczne.
(Bo są kiepsko napisane pod tym względem, np. Propel ma jeden wyjątek do tego nie ma kodu błędu i nie wiadomo co tak na prawdę się dzieje, komunikat mówi ale nie można tego w bloku catch niestety wykorzystać.)
WebCM
Zasadnicze pytanie - czy execute() oraz commit() zawsze rzucą wyjątkiem lub wyświetlą ostrzeżenie, jeśli rekord nie zostanie dodany do bazy (INSERT ...)? Istotne jest to, aby redaktor lub odwiedzający nie klął, że utracił swoje dzieło (artykuł, post...), nad którym długo pracował. Równie dobrze błędy mogą zostać wywołane przez zapytania niewchodzące do transakcji. Natomiast jeśli metoda nie wyrzuci wyjątku, użytkownik nawet nie dowie się, że coś jest nie tak. W zasadzie execute() i commit() zwracają tylko wartości TRUE i FALSE, więc w przypadku FALSE chyba zawsze rzucą wyjątkiem lub ostrzeżeniem.

Wyjątki może pozwalają dostosować wyświetlenie błędu do sytuacji (którego odwiedzający raczej nie powinien zobaczyć), ale PHP nie powinien wymuszać podania nazwy klasy w catch - wystarczy zmienić PDO np. na MySQLi i skrypt posypie się przy błędzie:
Kod
catch(PDOException $e)

Nie zbadałem jeszcze, czy użycie TRY powoduje spowolnienie kodu zamkniętego w klamrach tej instrukcji - też ważne.
nospor
Cytat
Wyjątki może pozwalają dostosować wyświetlenie błędu do sytuacji (którego odwiedzający raczej nie powinien zobaczyć), ale PHP nie powinien wymuszać podania nazwy klasy w catch - wystarczy zmienić PDO np. na MySQLi i skrypt posypie się przy błędzie:
Kod
catch(PDOException $e)
To co napisales ma ci jedynie pomoc rozroznic co spowodowalo wyjatek. jesli ci to zwisa i powiewa to zamiast PDOExeception daj poprostu Exception

ps:
Cytat
wystarczy zmienić PDO np. na MySQLi i skrypt posypie się przy błędzie
ciut kiepski argument. rownie dobrze moge napisac:
nie powinno sie nadawac nazw zmiennym. wystarczy ze zmienie nazwe i juz ten kod sie wysypie:
  1. <?php
  2. $zm='cos';
  3. //.....
  4. echo $zm;
  5. ?>

A teraz zmienie kod $zm='cos' na $zmiennainna='cos'l i juz mi sie echo $zm; wysypie 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.