Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Kiedy używać wyjątków?
zbig13
post
Post #1





Grupa: Zarejestrowani
Postów: 214
Pomógł: 0
Dołączył: 3.04.2004
Skąd: Legionowo

Ostrzeżenie: (0%)
-----


Witam!

Jestem w trakcie tworzenia obiektowego skryptu w php5. Zacząłem od własnego sterownika bazy danych. Napisałem taki kod:

  1. <?php
  2.  
  3. class DBMySQL
  4. {
  5.  
  6. private static $dbcon;
  7. private static $dbhandle;
  8. private static $query;
  9. private static $liczbaZapytan;
  10. private static $queryResult;
  11. private static $temp;
  12.  
  13. public function __construct()
  14. {
  15. self::$zapytan = 0;
  16. self::$dbcon = FALSE;
  17. }
  18.  
  19. public static function connect($host, $user, $pswd)
  20. {
  21. self::$dbcon = @mysql_connect($host, $user, $pswd);
  22. if (!self::$dbcon) {
  23. throw new Exception('Nie udało się połączyć z bazą danych.');
  24. }
  25. return self::$dbcon;
  26. }
  27.  
  28. public static function selectDb($dbname)
  29. {
  30. self::$dbhandle = @mysql_select_db($dbname);
  31. if (!self::$dbhandle) {
  32. throw new Exception('Nie udało się wybrać bazy.');
  33. }
  34. return self::$dbhandle;
  35. }
  36.  
  37. public static function query($query)
  38. {
  39. self::$liczbaZapytan++;
  40. self::$query = $query;
  41. return mysql_query(self::$query);
  42. }
  43.  
  44. public static function fetchArray($result)
  45. {
  46. self::$queryResult = $result;
  47. self::$temp = mysql_fetch_array(self::$queryResult);
  48. return self::$temp;
  49. }
  50.  
  51. public static function numRows($result)
  52. {
  53. self::$queryResult = $result;
  54. return mysql_num_rows(self::$queryResult);
  55. }
  56.  
  57. public static function realEscapeString($string)
  58. {
  59. return mysql_real_escape_string($string, self::$dbcon);
  60. }
  61.  
  62. public static function startTransaction()
  63. {
  64. self::query('BEGIN');
  65. }
  66.  
  67. public static function acceptTransaction()
  68. {
  69. self::query('COMMIT');
  70. }
  71.  
  72. public static function rollbackTransaction()
  73. {
  74. self::query('ROLLBACK');
  75. }
  76.  
  77. public static function returnQueries()
  78. {
  79. return $liczbaZapytan;
  80. }
  81.  
  82. }
  83.  
  84. ?>


W dwóch sytuacjach użyłem rzucania wyjątków w przypadku błedu (łączenie z bazą i wybieranie bazy). Chciałem też dać obsługe wyjątków do innych funkcji, np. query(), ale jakoś nie wyobrażam sobie później takiego wykonywania zapytań:
  1. <?php
  2. try {
  3. DBMySQL::query("SELECT * FROM tabela");
  4. } catch (Exception $e) {
  5. echo $e->getmessage();
  6. }
  7. ?>

Jest jakiś sposób na rzucanie wyjątków, żeby nie trzeba było ich później za każdym razem obsługiwać w kodzie? I czy warto rzucać wyjątki w przypadku takiej funkcji jak query(), lub numRows()?

Ten post edytował zbig13 27.03.2006, 07:56:12
Go to the top of the page
+Quote Post
2 Stron V   1 2 >  
Start new topic
Odpowiedzi (1 - 19)
Prph
post
Post #2





Grupa: Zarejestrowani
Postów: 338
Pomógł: 2
Dołączył: 4.03.2006
Skąd: Łódź

Ostrzeżenie: (0%)
-----


Nie rozumiem, dlaczego query to zle miejsce na wyjatek. Jak dla mnie idealne.

Mozesz tobic tak:

  1. <?php
  2.  
  3.  
  4. $wynik = DB::query('zapytanie');
  5. if(!$wynik)
  6. return fasle;
  7.  
  8. $wiersz = DB::fetch();
  9.  
  10. ..
  11. ..
  12.  
  13. idt.
  14.  
  15. ?>


albo, majac wyjatki w query:
  1. <?php
  2.  
  3. try
  4. {
  5. $this->_oDatabase->insert('session', $aToInsert);
  6.  
  7. $sQuery = 'SELECT id FROM session WHERE phpsessid = "'.$this->_sPHPSessionId.'"';
  8. $this->_oDatabase->query($sQuery);
  9.  
  10. $aRow = $this->_oDatabase->fetch();
  11. $this->_iNativeSessionId = $aRow['id'];
  12.  
  13. $this->_sPHPSessionId = $sPHPSessionId;
  14. }
  15. catch (Exception $oException)
  16. {
  17.  throw $oException;
  18. }
  19.  
  20. ?>


Czy to nie jest wygodne?
Go to the top of the page
+Quote Post
zbig13
post
Post #3





Grupa: Zarejestrowani
Postów: 214
Pomógł: 0
Dołączył: 3.04.2004
Skąd: Legionowo

Ostrzeżenie: (0%)
-----


Nie rozumiem tych Twoich przykładów. Mi chodzi po prostu o to, żeby w tej funkcji:
  1. <?php
  2. public static function query($query)
  3. {
  4. self::$liczbaZapytan++;
  5. self::$query = $query;
  6. return mysql_query(self::$query);
  7. }
  8. ?>

dodać rzucenie wyjątku jeśli nie uda się wykonać zapytania. Mogę zrobić tak jak w funkcji DBMySQL::connect(), ale wtedy przy każdym wykonaniu zapytanie będe musiał pisać:
  1. <?php
  2. try {
  3. DBMySQL::query("SELECT * FROM tabela");
  4. } catch (Exception $e) {
  5. echo $e->getmessage();
  6. }
  7. ?>

A wolałbym prościej:
  1. <?php
  2. DBMySQL::query("SELECT * FROM tabela");
  3. ?>
Go to the top of the page
+Quote Post
dr_bonzo
post
Post #4





Grupa: Przyjaciele php.pl
Postów: 5 724
Pomógł: 259
Dołączył: 13.04.2004
Skąd: N/A

Ostrzeżenie: (0%)
-----


Cytat
A wolałbym prościej: ....

przeciez i tak bedziesz musial sprawdzic czy zaputanie sie powiodlo, np.
  1. <?php
  2. if ( DBMySQL::query("SELECT * FROM tabela") )
  3. {
  4. ...
  5. }
  6. else
  7. {
  8.  ...
  9. } 
  10. ?>


nie musisz lapac wyjatkow po kazdym zapytaniu, tylko otaczasz try/catch od laczenia sie z baza, poprzez wybieranie bazy, zapytania az dorozlaczenia. No chyba ze potrzebujesz to zrobic inaczej.
Go to the top of the page
+Quote Post
zbig13
post
Post #5





Grupa: Zarejestrowani
Postów: 214
Pomógł: 0
Dołączył: 3.04.2004
Skąd: Legionowo

Ostrzeżenie: (0%)
-----


Ok juz rozumiem. Dzięki za pomoc (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)
Go to the top of the page
+Quote Post
SongoQ
post
Post #6





Grupa: Przyjaciele php.pl
Postów: 2 923
Pomógł: 9
Dołączył: 25.10.2004
Skąd: Rzeszów - studia / Warszawa - praca

Ostrzeżenie: (0%)
-----


Dorzuc tam transakcjem, logowanie czasow zapytania i explain
Go to the top of the page
+Quote Post
zbig13
post
Post #7





Grupa: Zarejestrowani
Postów: 214
Pomógł: 0
Dołączył: 3.04.2004
Skąd: Legionowo

Ostrzeżenie: (0%)
-----


Mam jeszcze jedno pytanie w związku z tym rzucaniem wyjątków.
Lepiej sprawdzać w metodzie klasy czy zapytanie się powiodło i w razie błędu wyrzucić wyjątek, czy może nie sprawdzać tego w metodzie klasy a po prostu w skrypcie sprawdzac czy wynik zapytania != false? Bo jak sprawdzam w metodzie, to cały skrypt mam objęty instrukcją try...catch i jak wystąpi jeden wyjątek to cały skrypt zostanie zatrzymany, a głupio trochę zatrzymać cały system jak tylko jedno zapytanie się nie powiedzie.
Więc jak lepiej?

Cytat(SongoQ)
  Dorzuc tam transakcjem, logowanie czasow zapytania i explain

A co to są transakcje? (IMG:http://forum.php.pl/style_emoticons/default/tongue.gif)
Go to the top of the page
+Quote Post
SongoQ
post
Post #8





Grupa: Przyjaciele php.pl
Postów: 2 923
Pomógł: 9
Dołączył: 25.10.2004
Skąd: Rzeszów - studia / Warszawa - praca

Ostrzeżenie: (0%)
-----


Cytat
A co to są transakcje?

W google znajdziesz. Dziwie sie ze w ogole zapytales, bo to jest podstawa relacyjnych baz danych. To tak jak bys pytal co to FOR w C
Go to the top of the page
+Quote Post
zbig13
post
Post #9





Grupa: Zarejestrowani
Postów: 214
Pomógł: 0
Dołączył: 3.04.2004
Skąd: Legionowo

Ostrzeżenie: (0%)
-----


Ok, już dodałem (kod w moim pierwszym poście) tylko nie wiem czy jest to przydatne w skrypcie, bo przecież zanim się doda jakieś dane do bazy to trzeba to sprawdzić wszystkimi możliwymi sposobami (IMG:http://forum.php.pl/style_emoticons/default/smile.gif) więc raczej nie ma potrzeby cofania zapytań. (przynajmniej mi się nigdy coś takiego nie zdarzyło)

A masz jakieś sugestie co do pierwszego pytania? (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)
Go to the top of the page
+Quote Post
Prph
post
Post #10





Grupa: Zarejestrowani
Postów: 338
Pomógł: 2
Dołączył: 4.03.2006
Skąd: Łódź

Ostrzeżenie: (0%)
-----


Jest bardzo wiele sytuacji w ktorzych korzystasz z transakcji. Sprzojrz na przyklad:

Kod
zapytanie = wstaw do bazy nowa glaerie;
if(baza->wykonaj(zaptanie))
{
  if(!utworz_katalog(strona/katalogi/uzytownik/nowa_galeria))
  {
    // okazalo sie nie nie mogl go utworzyc.
    zapytanie = usun z bazy wczesniej dodana galerie.
    if(!baza->wykonaj(zaptanie))
    {
       no i spojnosc danych poszla sie..;)
    }
  }
}


Z wykorzystaniem stansakcji
Kod
start_transakcji;

zapytanie = wstaw do bazy nowa glaerie;
if(baza->wykonaj(zaptanie))
{
  if(!utworz_katalog(strona/katalogi/uzytownik/nowa_galeria))
  {
    // okazalo sie nie nie mogl go utworzyc.
    abort;
  }
  else
    commit;
}


commit mozna w zasadzie pominac, bo zazwyczaj w bazie ustawuone jest autocommit i na koncy dane i tak zostana zapisane w bazie.

Pozdrawiam.
Go to the top of the page
+Quote Post
zbig13
post
Post #11





Grupa: Zarejestrowani
Postów: 214
Pomógł: 0
Dołączył: 3.04.2004
Skąd: Legionowo

Ostrzeżenie: (0%)
-----


No dobra przekonałeś mnie (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)

A co do tej funkcji query to chyba nie będe jednak dodawał w niej rzucania wyjątków, bo to troche bezsensu że cały skrypt się zatrzyma w przypadku błędu w zapytaniu.

@SongoQ
Logowanie czasów zapytania i explain postaram się dodać w najbliższym czasie (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)

Jeszcze raz dzięki wam za pomoc.

Pozdrawiam,
Zbig
Go to the top of the page
+Quote Post
SongoQ
post
Post #12





Grupa: Przyjaciele php.pl
Postów: 2 923
Pomógł: 9
Dołączył: 25.10.2004
Skąd: Rzeszów - studia / Warszawa - praca

Ostrzeżenie: (0%)
-----


Mozesz ewentualnie zrobic cos w rodzaju debug zapytania. Ustawiasz sobie jakis config gdzie podajesz max dla zapytania i np przy wersji debug wyswietlasz sobie zapytania ktore przeszly zadany czas a ktore nie, ktore sie wywalaja itd. Tam samo mozesz postapic z explain. Jak sobie zorganizujesz to juz zalezy tylko od Ciebie. Dla mnie np takie rzeczy sa bardzo wazne.
Go to the top of the page
+Quote Post
Vengeance
post
Post #13





Grupa: Zarejestrowani
Postów: 657
Pomógł: 2
Dołączył: 15.08.2003
Skąd: Łódź

Ostrzeżenie: (0%)
-----


Cytat
Bo jak sprawdzam w metodzie, to cały skrypt mam objęty instrukcją try...catch i jak wystąpi jeden wyjątek to cały skrypt zostanie zatrzymany, a głupio trochę zatrzymać cały system jak tylko jedno zapytanie się nie powiedzie.


Jak sama nazwa wskazuje, wyjątek służy do informowania o sytuacjach wyjątkowych, czyli takich po wystąpieniu których aplikacja musi być wstrzymana (ewentualnie jakiś blok operacji w aplikacji).

Dlatego stwierdzenie, że "trochę głupio jest zatrzymać system" jest samo w sobie bardzo głupie (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg) Chyba rozumiesz?
Go to the top of the page
+Quote Post
zbig13
post
Post #14





Grupa: Zarejestrowani
Postów: 214
Pomógł: 0
Dołączył: 3.04.2004
Skąd: Legionowo

Ostrzeżenie: (0%)
-----


Tak rozumiem, dlatego zrezygnowałem z wyjątków w funkcji query (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)
Go to the top of the page
+Quote Post
mike
post
Post #15





Grupa: Przyjaciele php.pl
Postów: 7 494
Pomógł: 302
Dołączył: 31.03.2004

Ostrzeżenie: (0%)
-----


Cytat(Vengeance @ 2006-03-28 20:42:59)
Cytat

Bo jak sprawdzam w metodzie, to cały skrypt mam objęty instrukcją try...catch i jak wystąpi jeden wyjątek to cały skrypt zostanie zatrzymany, a głupio trochę zatrzymać cały system jak tylko jedno zapytanie się nie powiedzie.


Jak sama nazwa wskazuje, wyjątek służy do informowania o sytuacjach wyjątkowych, czyli takich po wystąpieniu których aplikacja musi być wstrzymana (ewentualnie jakiś blok operacji w aplikacji).

Dlatego stwierdzenie, że "trochę głupio jest zatrzymać system" jest samo w sobie bardzo głupie (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg) Chyba rozumiesz?

~Vengeance mylisz się.
Wyjątek jest to nagła styuacja, na którą trzeba zareagować.

A przerwanie działania systemu/aplikacji to najgorsza reakcja.

Nie można sobie (a przynajmniej nie powinno) zatrzymać działania w fowolnej chwili bo wyskoczył jakiś wyjątek, no właśnie po to wyskoczył żeby nam powiedzieć że musimy zrobić coś inaczej niż planowaliśmy.

To zależy od natury wyjątku, ale powinniśmy ładnie dalej poprowadzić aplikacją na tory boczne, które zaprowadzą użytkownika do ładnego ekranu powiadamiającym go o błędzie. Wcześniej możemy wykonać wiele operacji: logować wyjątek, wysyłać maila do admina, ... .

Kill process to bardzo zły wybór.
Go to the top of the page
+Quote Post
SongoQ
post
Post #16





Grupa: Przyjaciele php.pl
Postów: 2 923
Pomógł: 9
Dołączył: 25.10.2004
Skąd: Rzeszów - studia / Warszawa - praca

Ostrzeżenie: (0%)
-----


Cytat
To zależy od natury wyjątku, ale powinniśmy ładnie dalej poprowadzić aplikacją na tory boczne, które zaprowadzą użytkownika do ładnego ekranu powiadamiającym go o błędzie.


Wyjatek moze rowniez sluzyc jako "redukcja" warunkow, wiec dokladnie zejscie na tory boczne jest tylko w wiekszosci przypadkow.
Go to the top of the page
+Quote Post
zbig13
post
Post #17





Grupa: Zarejestrowani
Postów: 214
Pomógł: 0
Dołączył: 3.04.2004
Skąd: Legionowo

Ostrzeżenie: (0%)
-----


To konkretnie jak lepiej robić? :
- Tam gdzie to możliwe umieszczać wyjątki
czy
- Unikać wyjątków i zastępować je warunkami
Go to the top of the page
+Quote Post
Vengeance
post
Post #18





Grupa: Zarejestrowani
Postów: 657
Pomógł: 2
Dołączył: 15.08.2003
Skąd: Łódź

Ostrzeżenie: (0%)
-----


mike_mech: Chodziło mi raczej oto, że stosowanie wyjątku dla np.:

  1. <?php
  2.  
  3. $request->Get('action');
  4.  
  5. ?>

Gdzie parametr action nie istnieje jest moim zdaniem głupie. Nie lubię, gdy ktoś załkowicie usuwa ify() na rzecz wyjątków.
Go to the top of the page
+Quote Post
DeyV
post
Post #19





Grupa: Zarząd
Postów: 2 277
Pomógł: 6
Dołączył: 27.12.2002
Skąd: Wołów/Wrocław




@ Vengeance - ale już w przypadku
system::createAction( 'news' );
wyrzucenie wyjątku może okazać się nazzwyczaj przydatne.
Zawsze wtedy masz możliwośc załadowania innej akcji, zrobienie czegoś innego.

Podobnie sytuacja wygląda np. z autoryzacją - nie masz uprawnień, to się zaloguj, i nie ważne jest to, w którym momencie system to zauważył. Ważne, że to dostrzegł, i w zwiazku z tym może coś z tym zrobić.

Apropo wyjątków i transakcji - mi osobiście bardzo podoba sie taki przykład:

  1. <?php
  2.  
  3.  
  4. try{
  5.  $Db->startTrans();
  6.  
  7.  $Db->Execute( pytanie );
  8.  $Db->Execute( pytanie2 );
  9.  $Db->Execute( pytanie3 );
  10.  
  11.  system::robCos();
  12.  
  13.  $Db->commitTrans();
  14. }
  15. catch( ExceptionDB $e ){
  16.  $Db->abortTrans();
  17. }
  18.  
  19. ?>


I niech ktoś w czytelniejszy sposób zapisze transakcje (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg)
Go to the top of the page
+Quote Post
Vengeance
post
Post #20





Grupa: Zarejestrowani
Postów: 657
Pomógł: 2
Dołączył: 15.08.2003
Skąd: Łódź

Ostrzeżenie: (0%)
-----


Ale czy ja mówię, że wyjątki są złe? Przykłady które podałeś są jak najbardziej dobre... i pokazują jak wyjątki są przydatne. Ale czy cieszyłbyś się, gdyby każda funkcja php zamiast np. false w razie błędu zwracała wyjątek? Ja nie... bo nie do tego są wyjątki by stosować je wszędzie gdzie się da. A że temat brzmi "kiedy używać wyjątków" chciałem zwrócić na to uwagę autora
Go to the top of the page
+Quote Post

2 Stron V   1 2 >
Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 25.08.2025 - 04:17