4

My question is about the correct way to catch exceptions in PHP. Based on the accompanying examples of the PHP MongoDB driver, I have created the following script:

<?php

try {

    $mng = new MongoDB\Driver\Manager("mongodb://localhost:2717");
    $query = new MongoDB\Driver\Query([], ['sort' => [ 'name' => 1], 'limit' => 5]);     

    $rows = $mng->executeQuery("testdb.cars", $query);

    foreach ($rows as $row) {

        echo "$row->name : $row->price\n";
    }

} catch (MongoDB\Driver\Exception\Exception $e) {

    $filename = basename(__FILE__);

    echo "The $filename script has experienced an error.\n"; 
    echo "It failed with the following exception:\n";

    echo "Exception:", $e->getMessage(), "\n";
    echo "In file:", $e->getFile(), "\n";
    echo "On line:", $e->getLine(), "\n";       
}

?>

The example is educational and meant to be run on the PHP CLI. In PHP CLI, we get all the exceptions on the console, but for didactic purposes, I wanted to catch exceptions in the try/catch block.

I have seen more Java code than PHP and therefore, catching a generic MongoDB\Driver\Exception\Exception does not look good to me. In Java, we catch specific exceptions and have multiple try/catch blocks for different kinds of exceptions.

The driver has the following Exceptions:

MongoDB\Driver\Exception\AuthenticationException
MongoDB\Driver\Exception\BulkWriteException 
MongoDB\Driver\Exception\ConnectionException 
MongoDB\Driver\Exception\ConnectionTimeoutException 
MongoDB\Driver\Exception\Exception 
MongoDB\Driver\Exception\ExecutionTimeoutException 
MongoDB\Driver\Exception\InvalidArgumentException 
MongoDB\Driver\Exception\LogicException 
MongoDB\Driver\Exception\RuntimeException 
MongoDB\Driver\Exception\SSLConnectionException 
MongoDB\Driver\Exception\UnexpectedValueException 
MongoDB\Driver\Exception\WriteException

Is this a kosher way to catch exceptions in PHP?

3 Answers 3

5

How about placing a switch statement in the catch part, and determine the exception's type with the instanceof language construct or the get_class() function?

For example:

[...]

} catch(\Exception $e) {
   switch (get_class($e)) {
     case 'MongoDB\Driver\Exception\AuthenticationException':
       // do stuff
       break;

     case 'MongoDB\Driver\Exception\BulkWriteException':
     //etc, etc...
   }
}

At first, I would examine the return values of get_class(), to make sure you I'm comparing the result with the exact exception names.

Sign up to request clarification or add additional context in comments.

1 Comment

We could do it in such a way, but is this the recommended way to catch exceptions in PHP? If so, why?
4

You can add multiple catch statements

<?php

try {

    $mng = new MongoDB\Driver\Manager("mongodb://localhost:2717");
    $query = new MongoDB\Driver\Query([], ['sort' => [ 'name' => 1], 'limit' => 5]);     

    $rows = $mng->executeQuery("testdb.cars", $query);

    foreach ($rows as $row) {

        echo "$row->name : $row->price\n";
    }

} catch (MongoDB\Driver\Exception\AuthenticationException $e) {

    echo "Exception:", $e->getMessage(), "\n";
} catch (MongoDB\Driver\Exception\ConnectionException $e) {

    echo "Exception:", $e->getMessage(), "\n";
} catch (MongoDB\Driver\Exception\ConnectionTimeoutException $e) {

    echo "Exception:", $e->getMessage(), "\n";
}

?>

2 Comments

This is how it is done in Java. The question is if it is the proper way to go. (I did not see code in PHP that way.) And the MongoDB\Driver\Exception\Exception also catches the ConnectionTimeoutException so maybe it is redundat to do it this way.
Yes, It is the Java way and same in the PHP. For more information you can see php.net/manual/en/language.exceptions.php. MongoDB\Driver\Exception\Exception is the generic class to catch all the exceptions and must be used as a fallback for exceptions not specifically caught in catch statements.
1

Adding multiple catch statement I think it's a better approach than switch. However, what if the exception isn't from these classes with a switch you should have a default case and also if you do it with multiple catches.

try {

$mng = new MongoDB\Driver\Manager("mongodb://localhost:2717");
$query = new MongoDB\Driver\Query([], ['sort' => [ 'name' => 1], 'limit' => 5]);     

$rows = $mng->executeQuery("testdb.cars", $query);

foreach ($rows as $row) {

    echo "$row->name : $row->price\n";
}

} catch (MongoDB\Driver\Exception\AuthenticationException $e) {
    echo "AuthenticationException:", $e->getMessage(), "\n";

} catch (MongoDB\Driver\Exception\ConnectionException $e) {
    echo "ConnectionException:", $e->getMessage(), "\n";

} catch (MongoDB\Driver\Exception\ConnectionTimeoutException $e) {
    echo "ConnectionTimeoutException:", $e->getMessage(), "\n";

}catch (\Exception $e) {
       echo "Exception:", $e->getMessage(), "\n";
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.