Как эффективно использовать try... catch блоки в PHP

Я использую try..catch блоки в моем PHP-коде, но я не уверен, правильно ли я их использовал.

Например, некоторые из моего кода выглядят следующим образом:

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

Итак, я группирую несколько операций с базами данных в одном блоке try/catch, потому что, если какое-либо исключение возникает в любой транзакции, я смогу обработать его.

Я делаю так, потому что считаю, что он более читабельным и эффективным, чем:

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

Хотя, я не уверен, что то, что я делаю, - это хорошая практика или просто ленивый способ поймать исключения.

Мое предположение заключается в том, что только если для исключения требуется специальная обработка, у него должен быть свой собственный блок try/catch, иначе группировка их в том же try/catch должна быть в порядке.

Итак, мои вопросы:

Есть ли преимущество использования блоков try/catch для транзакции базы данных? или я могу по-прежнему группировать несколько транзакций базы данных в одном и том же блоке try/catch без каких-либо проблем?

Можно ли встраивать блоки try/catch? Спасибо!

ИЗМЕНИТЬ

Оператор return был предназначен только для демонстрационных целей, но я также использую return в catch(), потому что я делаю запрос AJAX к этому методу, а Javascript ожидает объект JSON, а затем, если возникает исключение я вернуть пустой JSON-кодированный массив. Я просто подумал, что это не добавит никакой ценности, чтобы вставить конкретный код в мой пример.

Ответ 1

Важное примечание

В следующем обсуждении предполагается, что мы говорим о коде, структурированном, как в приведенном выше примере: независимо от того, какая альтернатива выбрана, исключение приведет к логическому прекращению способа делать то, что было в середине.


Пока вы намереваетесь делать то же самое, независимо от того, какой оператор в блоке try генерирует исключение, тогда лучше использовать один try/catch. Например:

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

Несколько блоков try/catch полезны, если вы можете и собираетесь обрабатывать сбой способом, соответствующим тому, что именно вызвало его.

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"
    }
}

Ответ 2

Для потомков ответ может быть слишком поздно. Вы должны проверить возвращаемое значение переменной и выбросить исключение. В этом случае вы уверены, что программа перейдет с того места, где исключение поднимается в блок catch. Найдите ниже.

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();

}

Ответ 3

Нет причин использовать один блок для нескольких операций, поскольку любое исключенное исключение предотвратит выполнение дальнейших операций после неудачного. По крайней мере, до тех пор, пока вы можете сделать вывод о том, какая операция не удалась из исключения. Это до тех пор, пока это нормально, если некоторые операции не обрабатываются.

Однако я бы сказал, что возвращение исключения делает лишь ограниченный смысл. Возвращаемое значение функции должно быть ожидаемым результатом какого-либо действия, а не исключения. Если вам нужно отреагировать на исключение в области вызова, то либо не поймайте исключение здесь внутри вашей функции, а в области вызова или повторно выбросите исключение для последующей обработки после выполнения некоторых протоколов отладки и т.п.

Ответ 4

Когда генерируется исключение, выполнение немедленно приостанавливается и продолжается в блоке catch{}. Это означает, что если вы поместите вызовы базы данных в один и тот же блок try{}, а $tableAresults = $dbHandler->doSomethingWithTableA(); выдает исключение, $tableBresults = $dbHandler->doSomethingElseWithTableB(); не произойдет. С вашей второй опцией $tableBresults = $dbHandler->doSomethingElseWithTableB(); будет по-прежнему возникать, поскольку она находится после блока catch{}, когда выполнение возобновлено.

В каждой ситуации нет идеального варианта; если вы хотите, чтобы вторая операция продолжалась независимо, тогда вы должны использовать два блока. Если допустимо (или желательно), чтобы вторая операция не выполнялась, вы должны использовать только один.

Ответ 5

Это более читаемый единственный блок catch try. Если его важность идентифицирует ошибку, я рекомендую настроить свои Исключения.

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

Ответ 6

в одном блоке catch catch вы можете сделать все, что лучше всего, чтобы поймать ошибку в разных блоках catch, если вы хотите, чтобы они отображали свое сообщение для определенных ошибок.

Ответ 7

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();
}

Ответ 8

Нет проблем с записью нескольких строк выполнения с одним блоком захвата try, как показано ниже

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

В момент, когда любое изъятие происходит либо в функции install_engine, либо install_break, управление будет передано функции catch. Еще одна рекомендация - правильно использовать свое исключение. Это означает, что вместо написания die('Message') всегда целесообразно иметь процесс исключения. Вы можете подумать об использовании функции die() при обработке ошибок, но не в обработке исключений.

Когда вы должны использовать несколько блоков catch try Вы можете подумать о множественном блоке catch try, если хотите, чтобы исключение из другого блока кода отображало различный тип исключения, или вы пытаетесь выбросить любое исключение из вашего блока catch, как показано ниже:

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')
}

Подробнее о том, как вы можете использовать блок catch try в разных случаях, можете ссылаться на мой блог на PHP Try Catch