Jak efektywnie używać try ... catch blocks w PHP

Używam try..łapać bloki w moim kodzie PHP, ale nie jestem pewien, czy używałem ich poprawnie.

Na przykład część mojego kodu wygląda następująco:

 try {
      $tableAresults = $dbHandler->doSomethingWithTableA();
      $tableBresults = $dbHandler->doSomethingElseWithTableB();
 } catch (Exception $e) {
      return $e;
 }

Więc grupuję wiele operacji bazodanowych w tym samym bloku try / catch, ponieważ jeśli wystąpi jakiś wyjątek w którejkolwiek z transakcji, będę w stanie go obsłużyć.

Robię to w ten sposób, ponieważ uważam, że jest bardziej czytelny i wydajny niż:

 try {
       $tableAresults = $dbHandler->doSomethingWithTableA();
 } catch (Exception $e) {
       return $e;
 }
 try {
       $tableBresults = $dbHandler->doSomethingWithTableB();
 } catch (Exception $e) {
       return $e;
 }
Chociaż nie jestem pewien, czy to, co robię, jest dobra praktyka lub po prostu leniwy sposób na wyłapywanie WYJĄTKÓW.

Moje założenie jest takie, że tylko jeśli wyjątek wymaga specjalnej obsługi, powinien mieć swój własny blok try/catch, w przeciwnym razie grupowanie ich w tym samym try/catch powinno być ok.

Więc moje pytanie brzmi:

Czy jest jakaś korzyść z używania bloków try/catch na transakcję bazy danych? czy nadal mogę grupować wiele transakcji bazodanowych w tym samym bloku try/catch bez żadnego problemu?

Czy można zagnieżdżać spróbuj / Złap bloki? Dzięki!

EDIT

Instrukcja return była głównie do celów demonstracyjnych, ale używam również returns w catch() ponieważ składam żądanie AJAX do tej metody, a Javascript oczekuje obiektu JSON, wtedy jeśli wystąpi wyjątek zwracam pustą tablicę zakodowaną w JSON. Po prostu pomyślałem, że nie dodałoby to żadnej wartości, aby umieścić konkretny kod w moim przykładzie.

Author: Mohd Abdul Mujib, 2013-07-09

8 answers

Ważna uwaga

Następująca dyskusja zakłada, że mówimy o kodzie o strukturze jak w powyższym przykładzie: bez względu na to, która alternatywa zostanie wybrana, wyjątek spowoduje, że metoda logicznie przestanie robić to, co było w środku.


Dopóki zamierzasz zrobić to samo bez względu na to, które oświadczenie w bloku try rzuca wyjątek, to na pewno lepiej jest użyć jednego try/catch. Na przykład:

function createCar()
{
    try {
      install_engine();
      install_brakes();
    } catch (Exception $e) {
        die("I could not create a car");
    }
}

Wiele try/catch bloki są przydatne, jeśli możesz i zamierzasz poradzić sobie z awarią w sposób specyficzny dla tego, co dokładnie ją spowodowało.

function makeCocktail()
{
    try {
        pour_ingredients();
        stir();
    } catch (Exception $e) {
        die("I could not make you a cocktail");
    }

    try {
        put_decorative_umbrella();
    } catch (Exception $e) {
        echo "We 're out of umbrellas, but the drink itself is fine"
    }
}
 81
Author: Jon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-09 13:44:06

Dla potomności odpowiedź może być za późno.Należy sprawdzić wartość zwracaną zmiennej i wyrzucić wyjątek. W takim przypadku masz pewność, że program przeskoczy z miejsca, w którym podnoszony jest wyjątek, do bloku catch. Znajdź poniżej.

try{
   $tableAresults = $dbHandler->doSomethingWithTableA();
   if (!tableAresults) 
     throw new Exception('Problem with tableAresults');

  $tableBresults = $dbHandler->doSomethingElseWithTableB();
   if (!tableBresults) 
     throw new Exception('Problem with tableBresults');
} catch (Exception $e) {
    echo $e->getMessage();

}
 18
Author: kodepet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-20 23:31:47

Nie ma powodu, aby używać jednego bloku do wielu operacji, ponieważ każdy wyrzucony wyjątek uniemożliwi wykonywanie dalszych operacji po nieudanej. Przynajmniej tak długo, jak można stwierdzić, która operacja nie powiodła się z przechwyconego wyjątku. To tak długo, jak jest w porządku, jeśli niektóre operacje są nie przetwarzane.

Powiedziałbym jednak, że zwracanie wyjątku ma tylko ograniczony sens. Wartość zwracana funkcji powinna być oczekiwanym wynikiem niektórych akcja, nie wyjątek. Jeśli chcesz zareagować na wyjątek w zakresie wywołania, to albo nie łap wyjątku tutaj wewnątrz funkcji, ale w zakresie wywołania lub ponownie wyrzuć wyjątek do późniejszego przetworzenia po wykonaniu logowania debugowania i tym podobnych.

 7
Author: arkascha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-09 13:45:28

Po wyrzuceniu wyjątku, wykonanie jest natychmiast zatrzymywane i kontynuowane w bloku catch{}. Oznacza to, że jeśli umieścisz wywołania bazy danych w tym samym bloku try{} i $tableAresults = $dbHandler->doSomethingWithTableA(); rzuci wyjątek, $tableBresults = $dbHandler->doSomethingElseWithTableB(); nie wystąpi. Z drugą opcją, $tableBresults = $dbHandler->doSomethingElseWithTableB(); będzie nadal występować, ponieważ jest po bloku catch{}, gdy wykonanie zostanie wznowione.

Nie ma idealnej opcji dla każdej sytuacji; jeśli chcesz, aby druga operacja była kontynuowana niezależnie, musisz użyć dwóch bloków. Jeśli jest dopuszczalne (lub pożądane), aby druga operacja nie wystąpiła, należy użyć tylko jednej.

 5
Author: IanPudney,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-09 13:38:14

Jest bardziej czytelny pojedynczy blok próbny. Jeśli jego ważne zidentyfikować rodzaj błędu polecam dostosować wyjątki.

try {
  $tableAresults = $dbHandler->doSomethingWithTableA();
  $tableBresults = $dbHandler->doSomethingElseWithTableB();
} catch (TableAException $e){
  throw $e;
} catch (Exception $e) {
  throw $e;
}
 5
Author: zongo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-19 19:24:43

W jednym bloku try catch możesz zrobić wszystko, co najlepszą praktyką jest złapanie błędu w innym bloku catch, jeśli chcesz, aby pokazał się z własnym Komunikatem dla poszczególnych błędów.

 0
Author: Amar Agrawal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-09 13:39:03
try
{
    $tableAresults = $dbHandler->doSomethingWithTableA();
    if(!tableAresults)
    {
        throw new Exception('Problem with tableAresults');
    }
    $tableBresults = $dbHandler->doSomethingElseWithTableB();
    if(!tableBresults) 
    {
        throw new Exception('Problem with tableBresults');
    }
} catch (Exception $e)
{
    echo $e->getMessage();
}
 0
Author: nitin kumar maurya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-19 12:57:07

Nie ma żadnego problemu z zapisaniem wielu linii wykonania z jednym blokiem try catch jak poniżej

try{
install_engine();
install_break();
}
catch(Exception $e){
show_exception($e->getMessage());
}

W momencie wystąpienia jakiegokolwiek wykonania w funkcji install_engine lub install_break kontrola zostanie przekazana do funkcji catch. Jeszcze jedna rekomendacja, aby prawidłowo zjeść wyjątek. Co oznacza, że zamiast pisać die('Message') zawsze wskazane jest, aby proces wyjątku był prawidłowo wykonywany. Możesz myśleć o użyciu funkcji die() w obsłudze błędów, ale nie w wyjątku obsługa.

Kiedy należy użyć multiple try catch block Możesz myśleć o wielu blokach try catch, jeśli chcesz, aby wyjątek different code block wyświetlał inny typ wyjątku lub próbujesz wyrzucić dowolny wyjątek z bloku catch, jak poniżej:

try{
    install_engine();
    install_break();
    }
    catch(Exception $e){
    show_exception($e->getMessage());
    }
try{
install_body();
paint_body();
install_interiour();
}
catch(Exception $e){
throw new exception('Body Makeover faield')
}

Aby uzyskać więcej informacji o tym, jak możesz używać try catch block w różnych przypadkach, możesz zapoznać się z moim blogiem na PHP Try Catch

 -1
Author: Ankur Kumar Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-02 23:19:53