3

I'd like to catch both errors and exceptions in my Silex app to wrap them in a custom JSON response that will always be returned to clients. I've found three basic methods:

$app->error()
Symfony\Component\Debug\ErrorHandler::register();
Symfony\Component\Debug\ExceptionHandler::register();

While I'm able to catch controller exceptions using error() I'm failing with php errors- they always end up in xdebug. I'm also failing to understand how error() and ExceptionHandler::register() interact with each other- do I need both? How can I make sure my error() response is JSON?

I've got the following example code right now:

use Silex\Application;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class Router extends Silex\Application
{
    function __construct() {
        parent::__construct();

        // routes
        $this->match('/{context}', array($this, 'handler'));

        // error handler
        $this->error(function(\Exception $e, $code) {
            return $this->json(array("error" => $e->getMessage()), $code);
        });
    }

    function handler(Request $request, $context) {
        // throw new \Exception('test'); // exception- this is caught
        $t = new Test(); // error- this is not caught

        return 'DONE';
    }
}

Symfony\Component\Debug\ErrorHandler::register();

$app = new Router();
$app->run();

2 Answers 2

6

With ErrorHandler::register(); you can catch your errors like exceptions

Example

use Symfony\Component\Debug\ExceptionHandler;
use Symfony\Component\Debug\ErrorHandler;

///bla bla bla some code

//catch all errors and convert them to exceptions
ErrorHandler::register();

try {
    //for example error happens here
    trigger_error( 'OH MY GOD, I AM ON FIRE' );
} catch ( \Exception $e ) {

    //for debugging you can do like this
    $handler = new ExceptionHandler();
    $handler->handle( $e );

    /*
    * ExceptionHendler class comments
    * It is mostly useful in debug mode to replace the default PHP/XDebug
    * output with something prettier and more useful.
    * so i suggest to create json response
    * and replace this code $handler = new ExceptionHandler();
    * $handler->handle( $e );
    */
    return new JsonResponse(
        array(
            'status' => 'error', 
            'message' => $e->getMessage()
        )
    );
}

with silex you can do next thing

ErrorHandler::register();
//register an error handler
$app->error(function ( \Exception $e, $code ) use ($app) {

    //return your json response here
    $error = array( 'message' => $e->getMessage() );

    return $app->json( $error, 200 );
});
Sign up to request clarification or add additional context in comments.

3 Comments

Mhm- this would need to work inside the Silex application. According to your code after ErrorHandler::register(), all errors should end up in $app->error() which they don't?
Much appreciated but no luck, My example doesn't work :/ It does work though with trigger_error as I'm noticing?
@andig $t = new Test(); is it produce fatal error?
1

I encounter this case today, and find a way to bind fatal error with Silex.

First, you need to bind an exception handler with Silex :

$app->error(function (\Exception $exception, $code) {
    // Something that build a nice \Symfony\Component\HttpFoundation\Response. This part is up to you.
    $response = MyExceptionFormatter::format($exception, $code);

    // A Silex exception handler must return a Response.
    return $response;
});

Now, we use the Symfony Debug Component to convert our errors.

// Convert simple errors into nice Exception, automaticaly handled by Silex.
Symfony\Component\Debug\ErrorHandler::register();

// Now, the hard part, handle fatal error.
$handler = Symfony\Component\Debug\ExceptionHandler::register($app['debug']);
$handler->setHandler(function ($exception) use ($app) {

    // Create an ExceptionEvent with all the informations needed.
    $event = new Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent(
        $app,
        $app['request'],
        Symfony\Component\HttpKernel\HttpKernelInterface::MASTER_REQUEST,
        $exception
    );

    // Hey Silex ! We have something for you, can you handle it with your exception handler ?
    $app['dispatcher']->dispatch(Symfony\Component\HttpKernel\KernelEvents::EXCEPTION, $event);

    // And now, just display the response ;)
    $response = $event->getResponse();
    $response->sendHeaders();
    $response->sendContent();
    //$response->send(); We can't do that, something happened with the buffer, and Symfony still return its HTML.
});

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.