I need to format error messages and output it in JSON format.
I have the following event subscriber:
namespace AppEventSubscriber;
use SymfonyComponentEventDispatcherEventSubscriberInterface;
use SymfonyComponentHttpKernelEventExceptionEvent;
use SymfonyComponentHttpKernelKernelEvents;
final class ExceptionSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [KernelEvents::EXCEPTION => 'onKernelException'];
}
public function onKernelException(ExceptionEvent $event) {/*..*/}
}
And following configuration in ./config/services.yaml
services:
_defaults:
autowire: true
autoconfigure: true
AppEventSubscriberExceptionSubscriber:
tags:
- {name: kernel.event_subscriber, event: kernel.exception}
This event subscriber is working when e.g. controller throws error.
But if I have some other error e.g. wrong DI injection
class FooBar {
public __constructor(NonExistingService $service) {/*..*/}
}
then output is still in Html format and as Symfony error page.
How to make that any error that Symfony catches is converted via my class to JSON?
Advertisement
Answer
I have found what’s wrong here.
Problem is that if you have e.g. configuration error, your events will be not yet hooked up.
In my code I have this:
// index.php
if ($_SERVER['APP_DEBUG']) {
umask(0000);
$errorHandler = Debug::enable();
}
$kernel = new Kernel();
/* .. */
This Debug::enable() actually sets error handler (without that there is only PHP default error handler at start).
I have extended Debug with my own class:
namespace AppError;
use SymfonyComponentErrorHandlerBufferingLogger;
use SymfonyComponentErrorHandlerDebug as SymfonyDebug;
use SymfonyComponentErrorHandlerErrorHandler;
class Debug extends SymfonyDebug
{
public static function enable(): ErrorHandler
{
if ($_SERVER['APP_DEBUG']) {
umask(0000);
$errorHandler = parent::enable();
}
return self::setDefaultErrorHandler($errorHandler ?? null);
}
private static function setDefaultErrorHandler(?ErrorHandler $errorHandler): ErrorHandler
{
$errorHandler ??= ErrorHandler::register(new ErrorHandler(new BufferingLogger(), true));
$errorHandler->setExceptionHandler([ExceptionHandler::class, 'renderException']);
return $errorHandler;
}
}
Now all errors goes through my AppErrorExceptionHandler where I can output it as JsonResponse