【问题标题】:How to create exception event listener for a specific controller action, to redirect to another action using its original argument?如何为特定控制器操作创建异常事件侦听器,以使用其原始参数重定向到另一个操作?
【发布时间】:2016-02-09 19:46:30
【问题描述】:

我有一个带有参数的动作,路线如下所示:

/cs/{id}

它是Cassette 控制器中的individualAction

有时,500 Internal Server Error - NoResultException 会出现异常 - 这是预期的行为。

我正在寻找重定向到另一个控制器操作editAction,当这种情况发生时,路线是这样的:

/cs/{id}/edit

它需要是特定于控制器的,因为我想用不同的控制器动作重复这个。它还需要保留原始操作的参数。

我一直在研究事件侦听器,但我不确定这是否过于矫枉过正,我正在努力找出如何使它们特定于操作 - 如果是的话,我很乐意将代码保留在控制器中更好的解决方案。

【问题讨论】:

  • 您是否有任何代码可以在其中获取/生成您的NoResultException 当然可以通过 EventListener 但应该知道事件发生时的情况。
  • 看看我的旧答案herehere和你想要的差不多。

标签: php symfony


【解决方案1】:

EventListener 最适合在引发异常时更改应用程序的行为。

使用类似的东西:

<?php

namespace AppBundle\EventListener;

use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\Routing\RouterInterface;
use Doctrine\ORM\NoResultException;

class ExceptionResponseListener
{
    public function __construct(RouterInterface $router)
    {
        $this->router = $router;
    }

    /**
     * @param GetResponseForExceptionEvent $event
     */
    public function onKernelResponse(GetResponseForExceptionEvent $event)
    {
        $request = $event->getRequest();
        $routeName = $request->get('_route');
        $exception = $event->getException();

        // Restrict the route by adding a check on the route name
        // Or a pattern of route names (!strpos($routeName, '_show'))
        // Or for many routes: (!in_array($routeName, ['xxx_show', ...]
        // Or the _controller: $request->get('_controller')
        // Output something like: "AcmeBundle\\Controller\\DefaultController::showAction"
        if ('expected_route_name' !== $routeName) {
            return;
        }    

        // Retrieve your param
        $params = $request->get('_route_params');

        if ($exception instanceof NoResultException) {
            // Create a redirection to the edit route
            $response = new RedirectResponse(
                $this->router->generate('your_edit_route', array('id' => $params['id']))
            );

            $event->setResponse($response);
        }
    }
}

并将其注册为服务:

services:
    # ...
    acme.kernel.listener.exception_listener:
        class: AppBundle\EventListener\ExceptionResponseListener
        tags:
            - {name: kernel.event_listener, event: kernel.exception, method: onKernelResponse}
        arguments: ['@router']

另一个简单的替代方法是直接在您的方法中对预期的操作进行转发/重定向,而不是抛出异常。

【讨论】:

  • 我对它的看法略有不同,但它 99% 是基于你的想法。我摆脱了支票并将其放入elseif - if ($exception instanceof NoResultException &amp;&amp; ($routeName == 'my_route')){...} elseif(...){...}else{return;}
  • 一个不错的方法。我会添加像if(!$exception instanceof NoResultException) { return; } 这样的优化,然后检查路线
猜你喜欢
  • 1970-01-01
  • 2014-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-06
  • 1970-01-01
  • 2014-12-31
  • 1970-01-01
相关资源
最近更新 更多