How to efficiently use try...catch blocks in PHP

PhpException HandlingTry Catch

Php Problem Overview


I have been using try..catch blocks in my PHP code, but I'm not sure if I've been using them correctly.

For example, some of my code looks like:

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

So I'm grouping multiple database operations in the same try/catch block because if any exception occurs in any of the transaction, I will be able to handle it.

I'm doing it that way because I think that it's more readable and efficient than:

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

Although, I'm not sure if what I'm doing is a good practice or just a lazy way to catch exceptions.

My assumption is that only if an exception requires special handling, it should have its own try/catch block, otherwise grouping them in the same try/catch should be ok.

So my question(s) are:

Is there any advantage of using try/catch blocks per database transaction? or can I still group multiple database transactions in the same try/catch block with no problem at all?

Is it ok to nest try/catch blocks? Thanks!

EDIT

The return statement was primarily for demonstration purposes only, but I'm also using returns in catch() because I'm making an AJAX request to that method, and Javascript is expecting a JSON object, then if an exception occurs I return an empty JSON encoded array. I just thought that It wouldn't add any value to put specific code in my example.

Php Solutions


Solution 1 - Php

Important note

The following discussion assumes that we are talking about code structured as in the example above: no matter which alternative is chosen, an exception will cause the method to logically stop doing whatever it was in the middle of.


As long as you intend to do the same thing no matter which statement in the try block throws an exception, then it's certainly better to use a single try/catch. For example:

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

Multiple try/catch blocks are useful if you can and intend to handle the failure in a manner specific to what exactly caused it.

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

Solution 2 - Php

For posterity sake,the answer maybe too late.You should check for the return value of the variable and throw an exception. In that case you are assured that the program will jump from where the exception is being raised to the catch block. Find below.

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

}

Solution 3 - Php

It's more readable a single try catch block. If its important identify a kind of error I recommend customize your Exceptions.

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

Solution 4 - Php

There is no reason against using a single block for multiple operations, since any thrown exception will prevent the execution of further operations after the failed one. At least as long as you can conclude which operation failed from the exception caught. That is as long as it is fine if some operations are not processed.

However I'd say that returning the exception makes only limited sense. A return value of a function should be the expected result of some action, not the exception. If you need to react on the exception in the calling scope then either do not catch the exception here inside your function, but in the calling scope or re-throw the exception for later processing after having done some debug logging and the like.

Solution 5 - Php

When an exception is thrown, execution is immediately halted and continues at the catch{} block. This means that, if you place the database calls in the same try{} block and $tableAresults = $dbHandler->doSomethingWithTableA(); throws an exception, $tableBresults = $dbHandler->doSomethingElseWithTableB(); will not occur. With your second option, $tableBresults = $dbHandler->doSomethingElseWithTableB(); will still occur since it is after the catch{} block, when execution has resumed.

There is no ideal option for every situation; if you want the second operation to continue regardless, then you must use two blocks. If it is acceptable (or desirable) to have the second operation not occur, then you should use only one.

Solution 6 - Php

in a single try catch block you can do all the thing the best practice is to catch the error in different catch block if you want them to show with their own message for particular errors.

Solution 7 - Php

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

Solution 8 - Php

There is no any problem to write multiple lines of execution withing a single try catch block like below

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

The moment any execption occure either in install_engine or install_break function the control will be passed to catch function. One more recommendation is to eat your exception properly. Which means instead of writing die('Message') it is always advisable to have exception process properly. You may think of using die() function in error handling but not in exception handling.

When you should use multiple try catch block You can think about multiple try catch block if you want the different code block exception to display different type of exception or you are trying to throw any exception from your catch block like below:

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionILikeTacosView Question on Stackoverflow
Solution 1 - PhpJonView Answer on Stackoverflow
Solution 2 - PhpkodepetView Answer on Stackoverflow
Solution 3 - PhpzongoView Answer on Stackoverflow
Solution 4 - PhparkaschaView Answer on Stackoverflow
Solution 5 - PhpIanPudneyView Answer on Stackoverflow
Solution 6 - PhpAmar AgrawalView Answer on Stackoverflow
Solution 7 - Phpnitin kumar mauryaView Answer on Stackoverflow
Solution 8 - PhpAnkur Kumar SinghView Answer on Stackoverflow