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