symfony2: hook into NotFoundHttpException for redi

2019-08-23 01:43发布

I'm currently migrating our project to symfony2. In our current codebase, we have a mechanism that allows us to define routings in a database table. We basically specify a regex the request URL gets matched against, and specify the URL the user should be redirected to. This redirecting works as a "last resort" right before throwing the 404. That way, these redirects never overwrite URLs that match existing actions and the matching is done lazily, only in case a 404 would have been thrown.

Is there a way to hook into Symfony's event model and listen for the NotFoundHttpException to do exactly that (e.g. issuing a 301/302 redirect if the URL matches some regex, instead of letting the 404 trough)?

1条回答
贪生不怕死
2楼-- · 2019-08-23 02:39

As you can see from this cookbook page, a "kernel.exception" event is fired whenever an exception is thrown. I'm not aware of there being a specific event for a NotFoundHttpException but I'd suggest creating your own listener service for all exceptions and then checking within the service for the type of exception and adding your custom logic.

(Note: I haven't tested this, but it should at least give you an idea of how this can be achieved.)

Configuration

acme.exception_listener:
    class: Acme\Bundle\AcmeBundle\Listener\RedirectExceptionListener
    arguments: [@doctrine.orm.entity_manager, @logger]
    tags:
        - { name: kernel.event_listener, event: kernel.exception, method: checkRedirect }

Listener service

namespace Acme\Bundle\AcmeBundle\Listener;

use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Doctrine\ORM\EntityManager;

class RedirectExceptionListener
{
    /**
     * @var \Doctrine\ORM\EntityManager
     */
    protected $em;

    protected $logger;

    function __construct(EntityManager $em, LoggerInterface $logger)
    {
        $this->em = $em;
        $this->logger = $logger;
    }


    /**
     * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
     */
    public function checkRedirect(GetResponseForExceptionEvent $event)
    {
        $exception = $event->getException();
        if ($exception instanceof NotFoundHttpException) {

            // Look for a redirect based on requested URI
            // e.g....
            $uri = $event->getRequest()->getUri();
            $redirect = $this->em->getRepository('AcmeBundle:Redirect')->findByUri($uri);
            if (!is_null($redirect)) {
                $event->setResponse(new RedirectResponse($redirect->getUri()));
            }
        }
    }
}
查看更多
登录 后发表回答