Search code examples
symfonysymfony-2.1symfony-2.3monolog

Call container inside ExceptionListener


I am using Symfony and i have created custom ExceptionListener to handle error.

class ExceptionListener
{
    protected $templating;
    protected $kernel;

    public function __construct(EngineInterface $templating, $kernel)
    {
        $this->templating = $templating;
        $this->kernel = $kernel;
    }

    public function onKernelException(GetResponseForExceptionEvent $event)
    {

            // exception object
            $exception = $event->getException();

            // new Response object
            $response = new Response();




          $response->setContent(
            // create you custom template AcmeFooBundle:Exception:exception.html.twig
                $this->templating->render(
                    'Exception/exception.html.twig',
                    array('exception' => $exception)
                )
            );

            // HttpExceptionInterface is a special type of exception
            // that holds status code and header details
            if ($exception instanceof HttpExceptionInterface) {
                $response->setStatusCode($exception->getStatusCode());
                $response->headers->replace($exception->getHeaders());

            } else {
                 $this->container->get('monolog.logger.db')->info('something happened 34', [
        'foo' => 'bar'
    ]);

                $response->setStatusCode(500);

            }
            if($exception instanceof FatalThrowableError){
                return  $this->templating->render(
                    'Exception/exception.html.twig'

                );

            }

            // set the new $response object to the $event
            $event->setResponse($response);

    }
}

and in service

 kernel.listener.acme_foo_exception_listener:
        class: AppBundle\Listener\ExceptionListener
        arguments: [@templating, @kernel]
        tags:
            - { name: kernel.event_listener, event: kernel.exception, method: onKernelException }

My aim is to when symfony throws exception i need to log error in database so i have created Logger event as per below link and it works fine when i called in controller but this event doesn't work when i called inside ExceptionListener.

I got following error

Notice: Undefined property: AppBundle\Listener\ExceptionListener::$container in

can any one help me how i can pass container inside Listener


Solution

  • As said by geoforce your service doesn't know about the container. Quick fix for this by changing the service arguments:

    arguments: [@templating, @container]
    

    While changing the listener constructor to:

    public function __construct(EngineInterface $templating, ContainerInterface $container)
    {
        $this->container = $container;
        // ...
    

    This should work, but injecting the entire container is quite an overkill and should definitely be done differently. Inject just what you need:

    arguments: [@templating, '@monolog.logger.db']
    

    And your constructor:

    public function __construct(EngineInterface $templating, 
    LoggerInterface $logger)
    {
        $this->logger = $logger;
        // ...
    

    Log with $this->logger->info(...).

    Since you've said that you're new to Symfony, I'd heavily recommend reading the DI component (http://symfony.com/doc/current/components/dependency_injection.html) docs. Understanding what DI does and how it works is mandatory to work with MVC frameworks like Symfony.