简体   繁体   English

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

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

From following this example I have managed to set up the below Listener/Before Filter to parse all requests to my API endpoint (ie. /api/v1) before any controller actions are processed. 通过遵循此示例,我成功设置了以下侦听器/之前过滤器,以在处理任何控制器动作之前解析对我的API端点(即/ api / v1)的所有请求。 This is used to validate the request type and to throw an error if certain conditions are not met. 这用于验证请求类型,如果不满足某些条件,则引发错误。

I would like to differentiate the error response based on the applications environment state. 我想根据应用程序环境状态区分错误响应。 If we are in development or testing, I simply want to throw the error encountered. 如果我们正在开发或测试中,我只是想抛出遇到的错误。 Alternatively, if in production mode I want to return the error as a JSON response. 另外,如果在生产模式下,我想将错误作为JSON响应返回。 Is this possible? 这可能吗? If not, how could I go about something similar? 如果没有,我该怎么做类似的事情?

I'm using Symfony v3.1.*, if that makes any difference. 我正在使用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()
                    // ]);
                }
            }
        }
    }

}

Unlike most events, the FilterControllerEvent does not allow you to return a response object. 与大多数事件不同,FilterControllerEvent不允许您返回响应对象。 Be nice if it did but oh well. 很好,但是很好。

You have two basic choices. 您有两个基本选择。

The best one is to simply throw an exception and then add an exception listener. 最好的方法是简单地引发一个异常,然后添加一个异常侦听器。 The exception listener can then return a JsonResponse based on the environment. 然后,异常侦听器可以根据环境返回JsonResponse。

Another possibility to to create a controller which only returns your JsonResponse then use $event->setController($jsonErrorController) to point to it. 创建仅返回JsonResponse的控制器的另一种可能性,然后使用$ event-> setController($ jsonErrorController)指向它。

But I think throwing an exception is probably your best bet. 但是我认为抛出异常可能是您最好的选择。

More details here: http://symfony.com/doc/current/reference/events.html 此处有更多详细信息: http : //symfony.com/doc/current/reference/events.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM