Search code examples
symfonyexceptionfosrestbundle

How to configure FOSRestBundle to not interfere with Custom Exception Controller


I have just updated my Symfony 2.7 page to 2.8. Beside Symfony itself a number of other packages have been updated as well. FOSRestBundle has been updated from version 1.4 to 2.1.

After the update the CustomExceptionController I configured for Twig does not work any more. Error like 404 or 500 show the default exception page instead of my custom page.

This is the configuration:

// app/config/config.yml
...
twig:
    exception_controller:  app.exception_controller:showAction


// src/MyAppBundle/Resources/config/services.yml
app.exception_controller:
    class: MyAppBundle\Controller\CustomExceptionController
    arguments: ['@twig', '%kernel.debug%', "@translator.default" ]


// src/MyAppBundle/Controller/CustomExceptionController.php
use Symfony\Component\Debug\Exception\FlattenException;    

class CustomExceptionController extends ExceptionController {   

protected $translator;

public function __construct(\Twig_Environment $twig, $debug, Translator $translator) {
    parent::__construct($twig, $debug);
    $this->translator = $translator;
}

public function showAction(Request $request, FlattenException $exception, DebugLoggerInterface $logger = null) {
    ...
}

With the help of another thread I was able to figure out, that the problem is caused by a config change I made in accordance with the FOSRestBundle Update notes:

removed the ability of the AccessDeniedListener to render a response.
Use the FOSRestBundle or the twig exception controller in complement.
...
After:
     fos_rest:
        access_denied_listener: true
        exception: true # Activates the FOSRestBundle exception controller

Following this hint and the Symfony docs, I added fos_rest:exception:enabled: true to the config.yml:

// Before the Update:
fos_rest:
    ...
    access_denied_listener:
        json: true  
    exception:
        codes:
            'Symfony\Component\Routing\Exception\ResourceNotFoundException': 404
            'Doctrine\ORM\OptimisticLockException': HTTP_CONFLICT
        messages:
            'Symfony\Component\Routing\Exception\ResourceNotFoundException': true

// After the Update:
fos_rest:
    ...
    access_denied_listener:
        json: true  
    exception:
        enabled: true  # <<< Added this line
        codes:
            'Symfony\Component\Routing\Exception\ResourceNotFoundException': 404
            'Doctrine\ORM\OptimisticLockException': HTTP_CONFLICT
        messages:
            'Symfony\Component\Routing\Exception\ResourceNotFoundException': true

According to the Symfony docs, the option fos_rest:exception:enabled: true was already necessary in version 1.4 to actually enable the FOS Exception Controller. Thus I am not sure, if the configuration was correct before the update and if the FOS Exception Controller worked as intended.

However, not it is necessary to set fos_rest:exception:enabled: true to correctly use the access_denied_listener.

So the Problem is: access_denied_listener should be able to work properly (fos_rest:exception:enabled: true has to be set) and my Twig Exception Controller should still handle exceptions (does not work if fos_rest:exception:enabled: true is set).

How do I properly set up / use the FOS Exception Controller without interfering with my Twig Exception Controller?


Solution

  • I think the answer can be found here:

    https://symfony.com/doc/master/bundles/FOSRestBundle/4-exception-controller-support.html

    FOSRestBundle defines two services for exception rendering, by default it configures fos_rest.exception.controller which only supports rendering via a serializer. In case no explicit controller is configured by the user and TwigBundle is detected it will automatically configure fos_rest.exception.twig_controller which additionally also supports rendering via Twig.

    So you need to extend: FOS\RestBundle\Controller\TwigExceptionController