Как эффективно использовать 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