Symfony:如何从Before过滤器(监听器)返回JSON响应


Symfony: How to return a JSON response from a Before Filter (Listener)?

从以下这个例子中,我已经成功地设置了下面的Listener/Before过滤器来解析所有请求到我的API端点(即:/api/v1),然后再处理任何控制器动作。这用于验证请求类型,并在不满足某些条件时抛出错误。

我想根据应用程序环境状态区分错误响应。如果我们在开发或测试中,我只想抛出遇到的错误。或者,如果在生产模式下,我想将错误作为JSON响应返回。这可能吗?如果没有,我怎么能做类似的事情呢?

我使用Symfony v3.1。*,如果有区别的话

namespace AppBundle'EventListener;
use AppBundle'Interfaces'ApiAuthenticatedController;
use Symfony'Component'HttpKernel'Event'FilterControllerEvent;
use Symfony'Component'DependencyInjection'ContainerInterface;
use Symfony'Component'HttpKernel'Exception'AccessDeniedHttpException;
class ApiBeforeListener
{
    /**
     * @var 'Symfony'Component'DependencyInjection'ContainerInterface
     */
    protected $container;
    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }
    /**
     * Validates a request for API resources before serving content
     *
     * @param 'Symfony'Component'HttpKernel'Event'FilterControllerEvent $event
     * @return mixed
     */
    public function onKernelController(FilterControllerEvent $event)
    {
        $controller = $event->getController();
        if (!is_array($controller))
            return;
        if ($controller[0] instanceof ApiAuthenticatedController) {
            $headers = $event->getRequest()->headers->all();
            // only accept ajax requests
            if(!isset($headers['x-requested-with'][0]) || strtolower($headers['x-requested-with'][0]) != 'xmlhttprequest') {
                $error = new AccessDeniedHttpException('Unsupported request type.');
                if (in_array($this->container->getParameter("kernel.environment"), ['dev', 'test'], true)) {
                    throw $error;
                } else {
                    // return json response here for production environment
                    // 
                    // For example:
                    // 
                    // header('Content-Type: application/json');
                    // 
                    // return json_encode([
                    //  'code'    => $error->getCode(),
                    //  'status'  => 'error',
                    //  'message' => $error->getMessage()
                    // ]);
                }
            }
        }
    }
}

与大多数事件不同,FilterControllerEvent不允许您返回响应对象。如果是这样就好了,但是,好吧。

你有两个基本的选择。

最好的方法是抛出一个异常,然后添加一个异常侦听器。然后异常监听器可以根据环境返回一个JsonResponse。

另一种方法是创建一个只返回JsonResponse的控制器,然后使用$event->setController($jsonErrorController)指向它。

但是我认为抛出一个异常可能是你最好的选择。

更多细节在这里:http://symfony.com/doc/current/reference/events.html