I'm building an app based on Silex 1.3. This is my first encounter with Silex, so I'm not very familiar with it.
I'd like to use my own error/exception handler, which is basically a class that registers itself and then will catch all errors, fatal errors, and uncaught exceptions and handle them, either with Whoops in development, or a graceful handler in production.
However, once I'm inside a silex controller, middleware, whatever, Silex will take over and use it's own error handling. Mine will still catch fatal errors, since Silex apparently doesn't hook into shutdown, but everything else is replaced with the default "Something went wrong" page from Silex.
I do understand that I can use $app->error() to override HOW Silex handles errors, but I haven't found a way to set things back to the original ErrorHandler from there, or to override WHETHER Silex handles errors.
So, does anyone know how to either a) tell Silex to use my error handler, using $app->error() or some other way, b) just disable error handling in Silex entirely, or c) as a last resort, get Silex to catch fatal errors so I can handle all three types from within $app->error()?
Since this is my first time using Silex, feel free to correct me or show me how you handle errors in Silex if there's a better way, but please also answer the question if you can.
Some example code:
// This will register itself and then handle all errors.
$handler = new ErrorHandler();
// These are all handled appropriately.
nonexistentfunction(); // Correctly caught by ErrorHandler::handleFatalError
trigger_error("example"); // Correctly caught by ErrorHandler::handlePhpError
throw new \Exception("example"); // Correctly caught by ErrorHandler::handleException
$app = new \Silex\Application();
$app->get('/', function () use ($app) {
// This is still handled correctly.
nonexistentfunction(); // Correctly caught by ErrorHandler::handleFatalError
// However, these are now overridden by Silex.
trigger_error("example"); // INCORRECTLY DISPLAYS SILEX ERROR PAGE.
throw new \Exception("example"); // INCORRECTLY DISPLAYS SILEX ERROR PAGE.
});
$app->run();
And a very simplified ErrorHandler for reference:
Class ErrorHandler
{
public function __construct()
{
$this->register();
}
private function register()
{
register_shutdown_function( array($this, "handleFatalError") );
set_error_handler(array($this, "handlePhpError"));
set_exception_handler(array($this, "handleException"));
}
// Etc.
}
I know the option the (b)
you can entirely disable Silex app error handler and after that, your custom error handler should work fine as you defined it.
Entirely disabled Silex error handler:
$app['exception_handler']->disable();
So, It will be like:
require_once 'Exception.php'; # Load the class
$handler = new ErrorHandler(); # Initialize/Register it
$app = new \Silex\Application();
$app->get('/', function () use ($app) {
nonexistentfunction();
trigger_error("example");
throw new \Exception("example");
});
$app->run();
You have to register specific provider in your app: https://github.com/whoops-php/silex-1
See Silex doc
Seemingly, you need to register an ExceptionHandler as well. Silex will turn fatal errors to exceptions in order to deal with them. Also, if I remember correctly, exceptions of this kind will be caught when 'thrown' inside controllers and middlewares (at least before middleware), but not inside models.
At the end, you can add the following to work with handling things.
// register generic error handler (this will catch all exceptions)
$app->error(function (\Exception $e, $exceptionCode) use ($app) {
//if ($app['debug']) {
// return;
//}
return \Service\SomeHelper::someExceptionResponse($app, $e);
});
return $app;
I hope that helped a little.
Please note that ExceptionHandler::disable() has been deprecated in 1.3 and removed in 2.0. So:
In Silex before 2.0:
$app['exception_handler']->disable();
In Silex 2.0+:
unset($app['exception_handler']);