我目前正在将项目迁移到symfony2。在我们当前的代码库中,我们有一种机制允许我们在数据库表中定义路由。我们基本上指定了请求URL匹配的正则表达式,并指定用户应该重定向到的URL。这种重定向在投掷404之前就是“最后的手段”。这样,这些重定向永远不会覆盖与现有动作匹配的URL,并且只是在抛出404的情况下才会懒惰地进行匹配。
有没有办法挂钩到Symfony的事件模型并监听NotFoundHttpException来完成那个(例如,如果URL匹配某些正则表达式而不是让404低谷,则发出301/302重定向)?
答案 0 :(得分:4)
从this cookbook page可以看出,只要抛出异常就会触发“kernel.exception”事件。我不知道NotFoundHttpException存在特定事件,但我建议为所有异常创建自己的侦听器服务,然后在服务中检查异常类型并添加自定义逻辑。
(注意:我没有对此进行过测试,但它至少应该让您了解如何实现这一目标。)
<强>配置强>
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 }
侦听服务
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()));
}
}
}
}