simont
simont

Reputation: 72527

Create an event subscriber to handle Error in Symfony 5.1

How can I create an event subscriber that fires when an Error like TypeError is thrown?

I have a controller that throws a TypeError. I want to create an event subscriber or listener capable of reacting to an Error, including TypeError.

Looking at the documentation, I've got an event subscriber for kernel.exception, but this does not get called when a TypeError is raised.

class MyController {
    /**
     * @Route("/error", name="error_listener_test")
     */
    public function bad() : Response
    {
        throw new TypeError('Bad Type');
    }
class FatalEventSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return [
            KernelEvents::EXCEPTION => [
                ['onException', 150], 
            ],
        ];
    }

    public function onException(ExceptionEvent $event)
    {
        $e = $event->getThrowable(); // Breakpoint here never triggers. 
    }
}

The KernelEvents::EXCEPTION triggers a Symfony\Component\HttpKernel\Event\ExceptionEvent which accepts a \Throwable, so I think it should be ok to accept the TypeError.

I've verified that the event subscriber is registered with the symfony console:


Registered Listeners for "kernel.exception" Event
=================================================

 ------- ---------------------------------------------------------------------------------- ----------
  Order   Callable                                                                           Priority
 ------- ---------------------------------------------------------------------------------- ----------
  #1      App\EventListener\FatalEventSubscriber::onException()                                150

I'm stepping through in a debugger, and I know that:

How can I configure the event subscriber to fire for these events?

Upvotes: 2

Views: 2397

Answers (1)

yivi
yivi

Reputation: 47308

Your listener is not being called because you are throwing a TypeError, which extends from \Error and not from \Exception.

Error and Exception are both instances of Throwable, but are generally considered different things which represent essentially different situations (which is why Errordoes not extend Extension).

As explained in the original RFC for the Throwable interface:

Users should generally be discouraged from catching Error objects except for logging or cleanup purposes as Error objects represent coding problems that should be fixed rather than runtime conditions that may be handled.

You can check the code for HttpKernel::handle(), and see that it only attempts to catch \Exception events, not \Throwable ones.

At least one issue was opened asking to widen the scope of this catch, but it was, IMO, correctly rejected.

TLDR: If you want your exception listener to be triggered, throw some kind of \Exception, no an \Error.

How can I configure the event subscriber to fire for these events?

I don't think any "configuration" will let you "listen" or catch TypeError errors with the Symfony event dispatching system, not directly. If you want to do so, you would need to create your own error handler, and maybe convert the TypeError to an ErrorException.

For a good example on error handlig, check how Monolog does it.

Upvotes: 2

Related Questions