1

How do i catch (custom)exceptions (with custom exception handler) that i have thrown in custom shutdown function ? I am not using any framework.

Example:

register_shutdown_function( 'shutdownFunction');
set_exception_handler(      'exceptionHandler');

function exceptionHandler(Exception $exception)
{
    // handle and log exception for later debugging...
}

function shutdownFunction()
{
    // something is not going right...
    if (someVariable != someValue)
        throw new RuntimeException('blah...'); // WILL NOT be caught by exception handler
}



// somewhere else in the code...
throw new Exception('something...'); // WILL be caught by exception handler (but not in shutdown function)

The script is using exceptions to communicate that it encountered an error during execution ie. unexpected variable passed to function, database failed to insert row etc...

1
  • 1
    Any uncaught exception will now goto exceptionHandler and end the terminate the PHP application. You cannot recover from a uncaught exception. You can catch errors with try...catch blocks Commented Aug 21, 2014 at 21:08

3 Answers 3

3

You simply cannot do this in php.

The register_shutdown_function callback is the last thing that happens in your PHP application. Trying to throw an exception in there will not do anything but invoke a standard php handler. There isn't much to be found on the web regarding these inner workings.

However, I created my own solution for directing it to a single function.

set_exception_handler and register_shutdown_functionare very different functions:

  • set_exception_handler receives a single argument Exception
  • register_shutdown_function receives no arguments by default

I've made it so that the set_exception_handler (which receives $exception as argument) sets a property which I can use in the register_shutdown_function.

$lastException = null;

set_exception_handler(function ($e) use (&$lastException) {
    $lastException = $e;
});

register_shutdown_function(function() use(&$lastException) {
    if($error = error_get_last()) {
        $lastException = new \ErrorException($error['message'], $error['type'], 1, $error['file'], $error['line']);
    }
    if($lastException) {
        if (APPLICATION_ENV === 'production') {
            Sentry\captureException($lastException);
        } else {
            var_dump($lastException);
        }
    }
});

I have no clue if this is a good way to solve the issue, but it allowed me to catch require unexisting_phpfile1389.php errors (Fatal) and regular throw \Exception()s in the same function.

Trying to throw an exception inside the shutdown handler will result in the following exception (how ironic):

( ! ) Fatal error: Uncaught Error: Can only throw objects in C:...\index.php on line 34

( ! ) Error: Can only throw objects in C:...\index.php on line 34

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

Comments

1

You can just wrap the body of your shutdownFunction with

function shutdownFunction()
    try {
        ...
    } catch (\Exception $e) {
        // do something
    }
}

and you will catch all exceptions becase Exception is the base class for all of them

2 Comments

What I meant is that I have one file with is an exception and error handling and logging and it is included to main script everytime user access any page. Application flow is controlled by throwing exceptions in failed statements. Everything works perfect until it comes to shutdown functions becouse PHP has already (somehow, don't know) unregistered my exception handler and it is not going to be called anymore if i throw any exception from now on.
This method of intercepting PHP error messages/exceptions seems to work well, except that it has not been fleshed out. I will post my version as an answer after more testing. Such intercepting depends on where it is done; in this case, it is done in a shutdown function, where the challenges are unique. It is hard work to design a simple but reliable error logging system that substitutes for PHP error and exception handling and also works with application-detected errors in various contexts.
0

It's quite simple:

function exception_handler (Exception $e) {

  if ($e instanceof DBException)
    error_handler (['query' => $e->getQuery ()]); // Your actions with your custom Exception object
  
}

function error_handler ($error) {

  if (isset ($error['query']))
      echo $error['query'];
  else
     // Another errors
  
}

set_error_handler ('error_handler', E_ALL);
set_exception_handler ('exception_handler');

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.