drzb7969753 2012-11-26 12:02
浏览 47
已采纳

symfony2:挂钩到NotFoundHttpException以进行重定向

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条回答 默认 最新

  • dtfo55908 2012-11-26 12:24
    关注

    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()));
                }
            }
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 使用ue5插件narrative时如何切换关卡也保存叙事任务记录
  • ¥20 软件测试决策法疑问求解答
  • ¥15 win11 23H2删除推荐的项目,支持注册表等
  • ¥15 matlab 用yalmip搭建模型,cplex求解,线性化处理的方法
  • ¥15 qt6.6.3 基于百度云的语音识别 不会改
  • ¥15 关于#目标检测#的问题:大概就是类似后台自动检测某下架商品的库存,在他监测到该商品上架并且可以购买的瞬间点击立即购买下单
  • ¥15 神经网络怎么把隐含层变量融合到损失函数中?
  • ¥15 lingo18勾选global solver求解使用的算法
  • ¥15 全部备份安卓app数据包括密码,可以复制到另一手机上运行
  • ¥20 测距传感器数据手册i2c