Подтвердить что ты не робот

Показывать конкретный маршрут вместо страницы с ошибкой (404) - Symfony2

Вместо страницы с ошибкой /404 я хочу просто показать страницу /sitemap. Конечно, я не хочу перенаправления, и я все же хочу, чтобы заголовок ответа HTTP 404 был установлен.

Возможно ли это? Все, что я вижу, это как установить шаблоны в Twig.

Я определенно не хочу перенаправления.

4b9b3361

Ответ 1

Как показано в книге по Symfony Cookbook, вы можете переопределять страницы ошибок двумя способами:

  • Переопределение шаблонов
  • Использование настраиваемого контроллера исключений

Если вы хотите показывать маршрут /sitemap при исключении 404 (HttpNotFoundException), вы можете переопределить шаблон исключения Twig, создав новый шаблон в app/Resources/TwigBundle/views/Exception/error404.html.twig.

Другой способ, который не показан в поваренной книге, - использовать прослушиватель событий. Когда ядро ​​встречает исключение, отправляется событие kernel.exception. По умолчанию это исключение попадает на прослушивание исключений, предоставляемое Twig. Вы можете создать свой собственный прослушиватель событий, который прослушивает событие 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)
    }
}

(Я не тестировал этот код, поэтому вы должны попробовать его сами! И вам, конечно же, нужно ввести шаблонный сервис в прослушиватель событий).

Ответ 2

У меня есть простое веб-приложение, состоящее из нескольких пакетов Symfony3, все контроллеры которых расширяют 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 Я уверен, что мой код можно улучшить, но он отлично работает.