Reputation: 72527
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:
TypeError
,FatalEventSubscriber::onException
) is not called.How can I configure the event subscriber to fire for these events?
Upvotes: 2
Views: 2397
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 Error
does 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