Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP] Błędy w klasach
Forum PHP.pl > Forum > PHP > Object-oriented programming
Babcia@Stefa
Witam, jak lepiej obsługiwać błędy z poziomu klasy?

trigger_error()" title="Zobacz w manualu PHP" target="_manual
Czy wyjątki?
  1. <?php
  2. throw new Exception('Nazwa klasy :: funkcja() : Jakis blad', 1);
  3. ?>


Do tej pory kożystałem z wyjątków, ale coś mnie podkusiło aby się zapytać co do tego trigger_error()" title="Zobacz w manualu PHP" target="_manual smile.gif

@edit
Zastanawiam się nad tym dlaczego iż wyjątki nie są aż takie wygodne...
Gdy ktoś ma error_reporting wyłączony to obsługuje klasę jak zwykłe funkcje z jądra PHP, a przy obsłudze wyjątków trzeba try {} i catch{} za każdym razem stosować przy tworzeniu obiektów.

Dziękuję, Babcia@Stefa
bim2
Ja bym obstał przy wyjątkach. Ale trochę inaczej. Często można spotkać ten sposób w wielu frameworkach.
  1. <?php
  2. class My_Exception extends Exception {}
  3. ?>


Wtedy, jeśli masz zamiar inaczej wyświetlać wiadomość
  1. <?php
  2. class My_Exception extends Exception {
  3. public function getMessage()
  4. {
  5. $sMessage = parent::getMessage();
  6. return 'Błąd: '.$sMessage;
  7. }
  8. }
  9. ?>

i w kodzie
  1. <?php
  2. thrown My_Exception('jakis tam blad');
  3. ?>


EDIT:
Nie lubie edycji postów. Co do try {} i catch{}. Ja w sowim kodzie wystarczy, że użyje ich raz. Przy uruchomieniu kontrolera, który uruchamia sobie resztę, ale wyjątek i tak zostanie złapany. Bo się w nim mieści.

PS. Przy __autoload() wyjątki siadają niestety sad.gif
wlamywacz
  1. <?
  2. function __autoload($class) {
  3. require_once './class/' . $class . '.class.php';
  4. }
  5.  
  6. define('FOLDER', './templates/');
  7.  
  8. try {
  9.  
  10. $ini_array = parse_ini_file("config.ini", true);
  11.  
  12. $db = new db;
  13. $db->setParam('user', $ini_array['mysql']['user']);
  14. $db->setParam('pass', $ini_array['mysql']['pass']);
  15. $db->setParam('name', $ini_array['mysql']['name']);
  16. $db->setParam('host', $ini_array['mysql']['host']);
  17. $db->connect();
  18.  
  19. $action = new action;
  20. $action->setParam('defClass', $ini_array['action']['defClass']);
  21. $action->setParam('startClass', $ini_array['action']['startClass']);
  22. $action->setParam('explode', $ini_array['action']['explode']);
  23. $action->setParam('exceptions', $ini_array['action']['exceptions']);
  24. $action->action();
  25.  
  26. } catch (Exception $e) {
  27. echo 'Wystąpił błąd systemu : <b>', $e->getMessage(), "</b>\n";
  28. }
  29. ?>


I po kłopocie
bim2
autoload" title="Zobacz w manualu PHP" target="_manual
Cytat
Informacja: Exceptions thrown in __autoload function cannot be caught in the catch block and results in a fatal error.

;-/
wlamywacz
Niestety sad.gif
Babcia@Stefa
  1. <?php
  2. public function Error($MESSAGE, $ID='')
  3. {
  4. if($this->ErrorReporting == 'Trigger')
  5. trigger_error($MESSAGE, E_USER_NOTICE);
  6. else
  7. throw new Exception('ClassName :: ' .$MESSAGE, $ID);
  8. }
  9. ?>


  1. <?php
  2. $this->Error('Opis', 1);
  3. ?>


Doszedłem do takiego rozwiązania.
bim2
Widzę, że chcesz to zrobić elastycznie, ale w przypadku błędów tak się nie da. Zobaczysz to później. Uchwyć się jednego rozwiązania (polecam wyjątki) i nim obsługuj błędy. Przecież i tak od ciebie zalezy jak błędy wyświetlisz, zapiszesz i co z nimi zrobisz. Można nawet robić na własnej klasie obsługi błędów, tylko po co, jeśli mamy udostępnione porządne narzędzie?

Ja wyjątki wyrzucam tradycyjnie, a później
  1. <?php
  2. catch(Syd_Exception $oException) {
  3. $oController->getPlugin('Error')->display($oException);
  4. }
  5. ?>

I display() zapisuje mi loga z linia, nazwa pliku oraz z post i get itd. oraz wyrzuca stosowny błąd na ekranie. Bardzo fajny jest tracker, dzięki któremu widzę przebieg ładowania programu.

EDIT: To błędów nie wrzucaj nigdy ozdobników tylko suche błędy. I jak najwiecej informacji, co pozwala znaleźć błąd.
Sedziwoj
@ Babcia@Stefa
Wyjątki są o wiele wygodniejsze, mimo że musisz umieszczać kod w bloku try{} to umożliwia Ci jednak rozpoznanie co to za błąd i naprawę.
Ale nie można tego robić, że masz jedną klasę wyjątków Exception, tylko każdy typ błędu powinien mieć swoją własną, czasem to będzie tylko zmiana nazwy aby móc zastosować pewną konstrukcję:
  1. <?php
  2. try{
  3. //jakiś kod
  4. }catch ( JakisMalyBlad $e ){
  5. //Obsługa tego błędu
  6. }catch ( JakisPowaznyBlad $e ){
  7. //Obsługa tego błędu, np. wyświetlenie komunikatu użytkownikowi, że coś jest nie t
    ak, 
  8. //a dodatkowo zapisujemy sobie to do logów czy cokolwiek innego.
  9. }//Nie musimy na tym poziomie wyłapywać wszystkich wyjątków, 
  10. //część możemy przepuścić dalej, i te co powodują że nie może działać strona, są o
    bsługiwane przez kontroler.
  11. ?>


No i to co napisałe bim2, możemy rozszerzać własne wyjątki, które dadzą nam takie metody które są nam potrzebne.
carbolymer
@Sedziwoj: nie trzeba tworzyć każdorazowo klasy do typu błędu (dobrze jest to robić, ale nie jest to niezbędne). W deklaracji klasy exception widzimy:
  1. <?php
  2. class Exception {
  3. (..)
  4. protected int $code ;
  5. (..)
  6. final public int getCode ( void )
  7. }
  8. ?>

I prototyp konstruktora wygląda następująco:
  1. <?php
  2. public Exception::__construct ([ string $message [, int $code ]] )
  3. ?>


Czyli zamiast tworzyć X klas, możemy po prostu wrzucać do parametru $code dowolną stałą / liczbę która może nam zidentyfikować błąd.

A przewaga wyjątków nad trigger_error() jest znaczna - za ich pomocą możesz opanować sytuację i nawet nie wypluwać info o błędzie tylko zaradzić jemu.
Sedziwoj
Cytat(carbolymer @ 3.07.2008, 22:33:41 ) *
@Sedziwoj: nie trzeba tworzyć każdorazowo klasy do typu błędu (dobrze jest to robić, ale nie jest to niezbędne).
Czyli zamiast tworzyć X klas, możemy po prostu wrzucać do parametru $code dowolną stałą / liczbę która może nam zidentyfikować błąd.


Wiesz, nierozróżnienie wyjątku jest przydatne, jeśli jego obsługa jest ta sama, czy prawie ta sama.
Ale jak jest błąd połączenia z baza danych i nieprawidłowe parametry, to jednak powinny to być inne wyjątki, bo co innego się robi. Jak już masz błąd połączenia, to możesz kodem opisać co jest przyczyną.
Taki ja mam pogląd.
carbolymer
@Sedziwoj: no ja się zgadzam z tobą, sam nawet stosuję te rozróżnienie na klasy, chciałem tylko przedstawić sprawę w innym świetle.
wrzasq
oczywiscie polecam rozwiazanie polegajace na wyjatkach. niewatpliwie jest ona bardziej elastyczne (ze wzgledu na mozliwosc chociazby zagniezdzenia blokow try{} catch{} wiec mozesz umiescic swoj starszy kod wewnatrz takiego bloku i nie bedzie problemu) a jednoczescie umozwiliajace dosc dobra kontrole nad przebiegiem wydarzen (jak widac na poszczegolnych juz przytoczonych przykladach mozna dosc szczegolowo kontrolowac zdarzenia zaleznie od tego, jaki blad wystapi). najwazniejsza przewaga wyjatkow nad trigger_error() jest to, ze jest to kontrukcja jezykowa (jak takze widac).

ze swojej strony moge dodac klase wyjatkow, ktora w nieznaczny sposob modyfikuje zachowanie klasy bazowej, a umozliwia proste rozroznienie wyjatkow tej samej rodziny po konkretnych przypadkach (kodach bledow):

  1. <?php
  2.  
  3. /**#@+
  4.  * @version 0.1.2
  5.  * @since 0.0.6
  6.  */
  7.  
  8. /**
  9.  * @package POT
  10.  * @author Wrzasq <wrzasq@gmail.com>
  11.  * @copyright 2007 (C) by Wrzasq
  12.  * @license <a href=\"http://www.gnu.org/licenses/lgpl-3.0.txt\" target=\"_blank\">http://www.gnu.org/licenses/lgpl-3.0.txt</a> GNU Lesser General Public License, Version 3
  13.  */
  14.  
  15. /**
  16.  * Generic exception class for error codes.
  17.  * 
  18.  * @package POT
  19.  */
  20. class E_OTS_ErrorCode extends Exception
  21. {
  22. /**
  23.  * Sets error code.
  24.  * 
  25.  * @param int $code Error code.
  26.  * @param string $message Optional error message.
  27.  */
  28. public function __construct($code, $message = '')
  29. {
  30. parent::__construct($message, $code);
  31. }
  32. }
  33.  
  34. /**#@-*/
  35.  
  36. ?>

http://opentibia.svn.sourceforge.net/viewv...S_ErrorCode.php

oczywiscie roznica jest nieznaczna, ale z poziomu kodu o wiele wygodniej jest obslugiwac kody bledow, niz ich wiadomosci.
bim2
Jeśli masz gdzieś rozpiskę tych kodów, co jaki znaczy. Mi prościej jest przekazać cały błąd i informację z nim związane, np "Can't load file [ścieżka do pliku]". Oczywiście gdy user nie ma praw wyświetla mu się identyfikator błędu oraz ja dostaje powiadomienie na emaila. Szybciej się debuguje aplikację niż szukać jaki kod co oznaczał.
dr_bonzo
Bledy phpowe sa do D....., nic ci nie daja, wywala napis na ekran [ktorego w 99% nie chcesz tam widziec] a program leci sobie dalej, co z tego ze nie polaczyles sie z baza, skrypcik proboje na tym nieistniejacym polaczeniu wywolywac zapytania [a wyjatek ucieknie ci poziom wyzej, a dokladniej do pierwszego catch'a i nie pozwoli ci na takie bezsensowne akcje w skrypcie].
Mozesz przeciez uzyc IF'y, wszedzie, prawie co linijke, az szlak cie trafi. No i tracisz jedna z wartosci zwracanych przez funkcje, ktora musisz przeznaczyc na pokazanie ze nastapil blad.

Ja nie korzystam z kodow bledow w wyjatkach [moze sie kiedys przydadza, ale na razie nie byly mi potrzebne], kazdy rodzaj bledu ma swoja klase np. RecordNotFound, FileNotFound, RoutingError, i jako msg przekazuje jakies dane odpowiednio NazwaKlasy + id, nazwa pliku, parametry requestu. Rozpoznawanie po kodzie bledu jest lipne, bo musisz dopisac funkcjonalnosc ktora juz masz [obsluge wielu catch'y], zamiast po prostu utworzyc kilka klas wyjatkow [1000x czytelniejsze]
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.