Show a specific route instead of error page (404) - Symfony2

前端 未结 3 1514
面向向阳花
面向向阳花 2020-12-15 10:08

Instead of an error page / 404 I want to just show the /sitemap page. Of course I don\'t want a redirect and I still want the 404 HTTP response header to be set.

Is

相关标签:
3条回答
  • 2020-12-15 10:44

    The easiest way is to create this file:

    • Symfony 3: /app/Resources/TwigBundle/views/Exception/error404.html.twig
    • Symfony 4: /templates/bundles/TwigBundle/Exception/error404.html.twig

    ... and copy this line into it:

    {{ render(controller('App\\Controller\\HomepageController::index')) }}
    

    That's it. This will show the home page with a 404 status code. It only works in prod environment (clear the cache!), since in dev and test Symfony always shows its exception page.

    References:

    • https://symfony.com/doc/current/controller/error_pages.html#overriding-the-default-error-templates
    • https://symfony.com/doc/current/templating/embedding_controllers.html
    • https://symfony.com/doc/current/controller/error_pages.html#testing-error-pages-during-development
    0 讨论(0)
  • 2020-12-15 10:46

    As shown in the Symfony Cookbook you can override error pages in two ways:

    • Overriding the templates
    • Using a custom exception controller

    If you only want to show the /sitemap route on a 404 (HttpNotFoundException) exception you could override the Twig exception template by creating a new template in app/Resources/TwigBundle/views/Exception/error404.html.twig.

    Another way that is not shown in the cookbook is using an event listener. When the kernel encounters an exception, a kernel.exception event is dispatched. By default, this exception is caught by the exception listening provided by Twig. You can create your own event listener which listens for the kernel.exception event and renders a page:

    <?php
    use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
    use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
    use Symfony\Component\HttpFoundation\Response;
    
    public function onKernelException(GetResponseForExceptionEvent $event)
    {
        if ($event->getException() instanceof NotFoundHttpException) {
            $response = $this->templating->renderResponse(/* sitemap */);
    
            $event->setResponse($response)
        }
    }
    

    (I haven't tested this code, so you should try it yourself! And you have to inject the templating service into the event listener yourself, of course).

    0 讨论(0)
  • 2020-12-15 10:56

    I have a simple web app composed by several Symfony3 bundles, all of whose controllers extend a BaseController. I have a AdminBundle too. To show a given page for every not existent url, I hacked (and made simpler) the original ExceptionController.php (from the TwigBundle):

    <?php
    
    namespace MyApp\AdminBundle\Controller;
    
    use Symfony\Bundle\FrameworkBundle\Controller\Controller;
    use Symfony\Component\HttpFoundation\Response;
    use Symfony\Component\HttpFoundation\Request;
    
    use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
    use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
    use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
    use MyApp\Controller\BaseController;
    
    use Symfony\Component\Debug\Exception\FlattenException;
    use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
    
    class ExceptionController extends BaseController
    {
        /**
         * Converts an Exception to a Response.
         *
         * @param Request              $request   The request
         * @param FlattenException     $exception A FlattenException instance
         * @param DebugLoggerInterface $logger    A DebugLoggerInterface instance
         *
         * @return Response
         * @throws \InvalidArgumentException When the exception template does not exist
         */
        public function showAction(Request $request, FlattenException $exception, DebugLoggerInterface $logger = null)
        {
            $currentContent = $this->getAndCleanOutputBuffering($request->headers->get('X-Php-Ob-Level', -1));
            $code = $exception->getStatusCode();
            return $this->render('MyappAdminBundle:Admin:error.html.twig',
                array(
                    'status_code' => $code,
                    'status_text' => isset(Response::$statusTexts[$code]) ? Response::$statusTexts[$code] : '',
                    'exception' => $exception,
                    'logger' => $logger,
                    'currentContent' => $currentContent,
                )
            );
        }
    
        /**
         * @param int $startObLevel
         *
         * @return string
         */
        protected function getAndCleanOutputBuffering($startObLevel)
        {
            if (ob_get_level() <= $startObLevel) {
                return '';
            }
    
            Response::closeOutputBuffers($startObLevel + 1, true);
    
            return ob_get_clean();
        }
    }
    

    I define my error template as I liked.

    I need to add the following line within config.yml

    twig:
        exception_controller: MyappAdminBundle:Exception:show
    

    ps I am sure my code can be improved, but it works fine.

    0 讨论(0)
提交回复
热议问题