Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Przechwytywanie wszystkich wyjatkow
Forum PHP.pl > Forum > PHP
marcio
Witam mam takie pytanie czy jesli wszystkie nasze wyjatki z aplikacji dziedzicza po Exception to czy robiac tylko:
  1. catch(Exception $e)
  2. {
  3. //
  4. }

Przechwyce kazdy wyjatek mojej aplikacji?
Jesli nie to idzie tego jakos dokonac?
Sry moglbym sprawdzic ale jest juz 3:00 a spac nie bede spokojnie jak nie zapytam ;p
Sephirus
Exception jest podstawą do dziedziczenia wyjątków "naszych" więc w skrócie: TAK - wszystkie "nasze" wyjątki zostaną złapane.

Ale zastanawia mnie to, że napisałeś w całej aplikacji...

Jeżeli szukasz rozwiązania, które wyłapuje jakiś wyjątek niezależnie od tego gdzie został rzucony (czyli tak zwane wyjątki nie obsłużone) to poczytaj o set_exception_handler wink.gif
marcio
Chodzi mi poprostu o przechwycenie kazdego wyjatki jaki moja aplikacja moze rzucic by potem zapisac wszystko do logow bez wyswietlania tresci bledu online.
Sephirus
No to użyj tego set_exception_handler to się nadaje do tego super - ale są dwie rzeczy:

1. To wyłapie tylko nie obsłużone wyjątki - więc jeśli gdzieś dasz try - catch i obsłuzysz wyjątek - to on już do tego nie trafi...

2. Nie jestem na 100% pewny czy po wykonaniu tej funkcji ustawionej w tym set_exception_handler można kontynuować skrypt (nie mam czasu zerknąć) - więc przyjrzyj się temu

Ale na bank chodzi Ci właśnie o to wink.gif

To wrzucasz przy ładowaniu aplikacji a dalej samo działa wink.gif
Fifi209
Ja bym raczej użył formy:

  1.  
  2. try {
  3.  
  4. }catch(JakasKlasaException $e) {
  5.  
  6. }catch(InnaKlasaException $e) {
  7.  
  8. }


W ten sposób zawsze wiesz jaki wyjątek łapiesz i czy zapisać go do logów czy nie
marcio
Zgadzam sie ale jak zapomne obsluzyc jakis wyjatek to wtedy lipa a tak zawsze zapisze do logow.

Mam tak i dziala tak jak powinno: http://pyp.net.pl/source/4f3afe99940bd
Fifi209
Tylko nie wiesz co rzuca Ci wyjątek wink.gif Wiesz gdzie, wiesz jaka wiadomość ale nie wiesz jaki to typ wyjątku
Sephirus
Cytat(Fifi209 @ 15.02.2012, 03:16:01 ) *
Tylko nie wiesz co rzuca Ci wyjątek wink.gif Wiesz gdzie, wiesz jaka wiadomość ale nie wiesz jaki to typ wyjątku


Hmm nie zgadzam się z Tobą smile.gif

Obiekt wyjątku przekazywany jest do Exception_Handlera w całości zatem - wiemy o nim wszystkto - możemy uzyć instanceof czy po prostu wypisać jakiej klasy jest wyjątek smile.gif Mam coś takiego i śmiga smile.gif

Dodatkowo jest oczywiście dostępny w nim trace i cała ścieżka jego rzucenia...

AFAIK - nie ma żadnego problemu smile.gif
by_ikar
Cytat(Fifi209 @ 15.02.2012, 03:16:01 ) *
Tylko nie wiesz co rzuca Ci wyjątek wink.gif Wiesz gdzie, wiesz jaka wiadomość ale nie wiesz jaki to typ wyjątku

Error handler który rzuca errorexception

Sam z takiego rozwiązania korzystam i nie muszę się tam gdzie mi to nie potrzebne, bawić w try/catch w exception handler łapie moje wyjątki.

Exception handler zatrzymuje wykonywanie się skryptu, ale jeżeli gdzieś powiedzmy pod koniec całego naszego skryptu będzie rzucany wyjątek, wtedy wszystko co wcześniej wysłaliśmy do przeglądarki, się pokaże, do miejsca gdzie jest rzucany wyjątek. Dobrze użyć ob_end_clean.

Symfony w wersji 1.4 i wersji 2 korzysta z podobnego rozwiązania. Wyjątki są tam chociażby dla błędów http rzucane (404, 403, 501 itp).
marcio
No wlasnie nazwe wyjatku mozna sobie "wyciagnac".

Ale jak wlasnie zrobic by strona tak czy siak sie wczytywala jesli wystapi wyjatek nie przechwycony?!?
Tzn z tym ob_end_clean?

@fifi209
  1. class Exception_Handler
  2. {
  3. public static function Handler(Exception $e)
  4. {
  5. $eName = new ReflectionClass($e);
  6. $class = $eName -> getName();
  7. $exception = "Uncaught: ".$class." ";
  8. $exception .= date('d-m-Y H.i.s');
  9. $exception .= "\n";
  10. $exception .= "File: ".$e -> getFile();
  11. $exception .= " Line: ".$e -> getLine()."\n";
  12. $exception .= "Message: ".$e -> getMessage()."\n\n";
  13. file_put_contents(DIR_LOG.'logs.php', $exception, FILE_APPEND | LOCK_EX);
  14. }
  15. }


Ogolnie jak ktos moze pokazac jak moge wyswietlic strone uzywajac set_error_handler() i set_exception_handler().
Lub poprostu wczytac wtedy strone z bledem z trescia typu: Wystapil blad podczas ladowania witryny.

EDIT:

W przypadku "rzucienia" error'a/wyjatku jaki error moge zwrocic?
Myslalem nad 503 - Service Unavailable jedyny ktory wydaje mi sie byc wporzadku!
Sephirus
418 - I'm a teapot biggrin.gif hehehe

A tak na serio to możesz rzucić w zależności od tego czego dotyczy wyjątek różny błąd.

404 - wiadomo - jak nie ma strony (błędny kontroler itp...)
403 lub 401 - jeśli chcesz zrobić sprawdzanie uprawnień na zasadzie rzucania wyjątku typu "Auth_Exception" itp...

500 lub 503 - jeśli to jakiś poważny błąd

Zerknij sobie
marcio
@up wiem sprawdzalem wlasnie na wiki.
Nie potrzebuje az takiej dokladnosci lecz jakis ogolny http status code, najbardziej odpowiednim wydaje mi sie wlasnie ten o kodzie nr 503.
by_ikar
Zerknij jak to jest zrobione w symfony. Tam nie została użyta klasa reflection, tylko poprzez instanceof jest sprawdzane czy powiedzmy jest to jakaś klasa wyjątku, która dziedziczy HttpException. Gdzie HttpException z kolei dziedziczy RuntimeException.
W symfony masz taki katalog:

Kod
symfony.2.0.9\vendor\symfony\src\Symfony\Component\HttpKernel\Exception


W tym katalogu masz wyjątki http, a w tym katalogu:

Kod
symfony.2.0.9\vendor\symfony\src\Symfony\Component\HttpKernel\Debug


masz error handlera i exception handlera. Widzę że teraz jest to nieco inaczej zrobione, bo w wczesnej wersji 2, całkiem inaczej wyglądał ten handler, tzn była możliwość wybrania szablonu dla błędu, że można było rzucić błąd np w json. A teraz widzę że uznali że lepiej jest rzucać wszystkie błędy w html i nie angażować do tego inne klasy (przykładowo klasa templatek), które mogłyby spowodować dodatkowe błędy (tak mi się wydaje, bo swego czasu też się nad tym zastanawiałem wink.gif).

Nie wiem szczerze mówiąc jak to jest w innych frameworkach, ale podejrzewam że jest podobnie rozwiązane, poprzez kilka dodatkowych klas wyjątków, bo w sumie jest to najlepsze wyjście i wtedy wystarczy tylko rzucić wyjątek i już mamy piękną stronę błędu:

  1. throw new NotFoundHttpException('jakies info, ktore mozna zapisac w logach');


Na szybo przeszukałem dokumentacje kohany i tam jest to bardzo podobnie rozwiązane: http://kohanaframework.org/3.2/guide/kohan...als/error-pages również jest sprawdzanie czy dany wyjątek dziedziczy HTTP_Exception i jeżeli tak, dorzucany jest stosowny kod, który zawiera wyjątek. Powiedziałbym że jest to niemal identycznie jak w symfony rozwiązane.

W zendzie i pozostałych frameworkach najpewniej jest podobnie, aczkolwiek, nie identycznie wink.gif osobiście sam z dość zbliżonego do symfony rozwiązania korzystam i chwalę sobie wink.gif
marcio
Musze przyznac ze podgladalem idee Kohany 3.x i symfony tez(mniej ale zerknolem) jednak za duzo tam tego jest nie potrzebuje 50 klas z wyjatkami moj system nie jest az tak rozbudowanu wiec o blad jest troche trudniej.
Potrzebuje dobrych rozwiazan jednak nie az tak wyrafinowanych.
by_ikar
Um, jakich 50 klas? biggrin.gif Masz takie klasy:

ErrorHandler -> rzuca błędy php jako wyjątki
ExceptionHandler -> przechwytuje wyjątki
HttpException -> wyjątek do którego prócz wiadomości/kodu przekazywany jest kod błędu http (404. 403, 401, 500 etc) i w zasadzie wystarczy ci tylko ta klasa, bo przecież możesz ten kod błędu wprowadzić ręcznie
NotFoundHttpException -> dziedziczy HttpException dokładając do rodzica błąd http 404
AccessDeniedHttpException -> dziedziczy po HttpException dodając do rodzica błąd http 403

I tyle w sumie klas ci wystarczy, bo ustawiasz sobie w ExceptionHandler że dla każdego innego wyjątku, który nie dziedziczy po HttpException ustawiasz kod błędu http na 500, co możesz w handlerze do którego ścieżkę ci podałem odnaleźć w lini 74:

  1. $code = $exception instanceof HttpExceptionInterface ? $exception->getStatusCode() : 500;


Jest to raptem 5 klas, z czego 2 to handler, i dwie to są klasy które dziedziczą jedną klasę i są w sumie "opcjonalne". Bo można tak jak wyżej napisałem, zrobić to na jednej klasie i rzucać błędy http poprzez tą klasę. Bo generalnie chodzi tutaj o kod błędu który przesyłasz do przeglądarki i sposób w jaki możesz rozpoznawać, że ten wyjątek taki kod błędu przekazał, zamiast bawić się z reflection wink.gif

Czy to jest 50 klas, to bym dyskutował wink.gif
marcio
@by_ikar rozumiem jednak jakos wole moje rozwiazanie.

Mam jeszcze jedno pytania.

Jak reagujecie gdy wystapi wam jakis przechwycony wyjatek.To znaczy co robicie w bloku catch() { }?!?
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.