【问题标题】:Show a specific route instead of error page (404) - Symfony2显示特定路线而不是错误页面(404) - Symfony2
【发布时间】:2013-04-13 01:05:22
【问题描述】:

我只想显示 /sitemap 页面,而不是错误页面 / 404。当然我不想要重定向,我仍然想要设置 404 HTTP 响应头。

这可能吗?我只能看到如何在 Twig 中设置模板。

我绝对不想要重定向。

【问题讨论】:

    标签: symfony


    【解决方案1】:

    the Symfony Cookbook 所示,您可以通过两种方式覆盖错误页面:

    • 覆盖模板
    • 使用自定义异常控制器

    如果您只想在 404 (HttpNotFoundException) 异常中显示 /sitemap 路由,您可以通过在 app/Resources/TwigBundle/views/Exception/error404.html.twig 中创建新模板来覆盖 Twig 异常模板。

    说明书中未显示的另一种方法是使用事件侦听器。当内核遇到异常时,将调度kernel.exception 事件。默认情况下,这个异常会被 Twig 提供的异常监听捕获。您可以create your own event listener 监听kernel.exception 事件并呈现页面:

    <?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)
        }
    }
    

    (我没有测试过这段代码,所以你应该自己尝试一下!当然,你必须自己将模板服务注入到事件监听器中)。

    【讨论】:

    • 谢谢,我认为事件侦听器是可行的方法,但 $this-> 模板无效。我也尝试过 $event->template。我认为通常的控制器方法不可用。我得到一个未定义的属性: Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent::$templating in...
    • 你是对的,通常的控制器方法不可用,因为它们是服务方法调用的别名。您应该在服务描述中自己将templating 服务注入事件侦听器。
    • 当时我并没有意识到这只是设置了一个 Twig 模板,而不是一个实际的页面或控制器。
    • “模板”服务仅显示 Twig 模板,不呈现控制器
    • 当然它不会渲染控制器。这就是控制器的工作。但它应该呈现模板...您可以检查 Controller 类的 the source 以查看用于在控制器中呈现模板并将这些服务注入事件侦听器的内容。
    【解决方案2】:

    我有一个由几个 Symfony3 包组成的简单 Web 应用程序,所有这些包都扩展了 BaseController。我也有一个 AdminBundle。为了显示每个不存在的 url 的给定页面,我破解了(并简化了)原始 ExceptionController.php(来自 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();
        }
    }
    

    我根据自己的喜好定义我的错误模板。

    我需要在 config.yml 中添加以下行

    twig:
        exception_controller: MyappAdminBundle:Exception:show
    

    ps 我确信我的代码可以改进,但它工作正常。

    【讨论】:

      【解决方案3】:

      最简单的方法是创建这个文件:

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

      ...并将这一行复制到其中:

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

      就是这样。这将显示带有 404 状态代码的主页。它只适用于prod 环境(清除缓存!),因为在devtest Symfony 总是显示其异常页面。

      参考资料:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-01-09
        • 2019-03-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-06
        • 1970-01-01
        相关资源
        最近更新 更多