Skip to content

Instantly share code, notes, and snippets.

@EmanueleMinotto
Created January 29, 2015 21:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save EmanueleMinotto/ab46019a4e5f953a1c69 to your computer and use it in GitHub Desktop.
Save EmanueleMinotto/ab46019a4e5f953a1c69 to your computer and use it in GitHub Desktop.
PHP Exceptions Handlers

Exceptions Handlers

Starting from an idea of @lastguest, I'm writing this code to allow a chain of handlers.

What's the problem? Main problem is that more than one exception handlers aren't allowed so easily.

Usage

Code is started when you include the script, converts errors in exceptions and gets only the last exceptions handler.

<?php
set_exception_handler(function () { echo 0; });
set_exception_handler(function () { echo 1; });

$handlers = require_once('handlers.php');

$handlers(function () { echo 2; });
$handlers(function () { echo 3; });

throw new Exception;

// Output: 123
?>

a function is appended to other exceptions handlers by default, but you can prepend it settings the third parameter to false

<?php
$handlers = require_once('handlers.php');

$handlers(function () { echo 1; });
$handlers(function () { echo 2; });
$handlers(function () { echo 3; }, false);
$handlers(function () { echo 4; });

throw new Exception;

// Output: 3124
?>

Errors are Exceptions?

I don't want to start a discussion (but I would be happy to read your comments and opinions). I "redirected" error to exceptions to work with only one type of objects.

<?php
return call_user_func(function () {
/**
* exceptions callbacks
* @var array
*/
static $callbacks = array();
// errors are exceptions
set_error_handler(function ($errno, $errstr, $errfile, $errline) {
throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}, E_ALL);
/**
* This placeholder is used only to retrieve last defined handler
* @var callable
*/
$placeholder = set_exception_handler(null);
// bootstrap
if (empty($callbacks) && $placeholder) {
array_push($callbacks, $placeholder);
}
// This function is used to allow a chain of exceptions.
return function ($new, $append = true) use (&$callbacks) {
// type control
if (!is_callable($new)) {
throw new BadFunctionCallException(
'Argument 1 must be callable, '
. gettype($new) . ' given'
);
} elseif (!is_bool($append)) {
throw new BadFunctionCallException(
'Argument 2 must be boolean, '
. gettype($append) . ' given'
);
}
/**
* $append is used to switch from push to unshift
* @link http://it2.php.net/manual/en/function.array-push.php
* @link http://it2.php.net/manual/en/function.array-unshift.php
*/
if ($append) {
array_push($callbacks, $new);
} else {
array_unshift($callbacks, $new);
}
/**
* $old contains the function previously defined as the exception handler.
* Everytime this function will be invoked create a closure of the new and old functions.
* @link http://it2.php.net/manual/en/function.set-exception-handler.php
* @var Closure
*/
set_exception_handler(function () use ($callbacks) {
foreach ($callbacks as $callback) {
call_user_func_array($callback, func_get_args());
}
});
};
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment