symfony 3控制器中的自定义注释

时间:2017-08-10 15:30:33

标签: php symfony annotations doctrine

所以问题非常简单。我的控制器中的代码已经变得多余了,我决定为它做一个注释。

if (!$request->getContentType() === 'json' ) {
        return new JsonResponse(array('success' => false));
    }
    $content = $request->getContent();

    if(empty($content)){
        throw new BadRequestHttpException("Content is empty");
    }
    $data = json_decode($content, true);
    if(empty($data) || !array_key_exists('type', $data)) {
        return new JsonResponse(array('success' => false));
    }

如何制作自定义注释@CheckRequest,我可以在其中使用$ request对象作为参数?

2 个答案:

答案 0 :(得分:9)

你需要制作一个自定义注释,然后是一个注入注释阅读器并处理 kernel.controller 事件的监听器:

注释

/**
 * @Annotation
 */
class CheckRequest
{
}

服务定义

services:
    controller_check_request:
        class: AppBundle\EventListener\ControllerCheckRequestListener
        tags:
            - { name: kernel.event_listener, event: kernel.controller, method: onKernelController}
        arguments:
            - "@annotation_reader"

监听器:

namespace AppBundle\EventListener;

use AppBundle\Annotation\CheckRequest;
use Doctrine\Common\Annotations\Reader;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;

class ControllerCheckRequestListener
{
    /** @var Reader */
    private $reader;

    /**
     * @param Reader $reader
     */
    public function __construct(Reader $reader)
    {
        $this->reader = $reader;
    }

    /**
     * {@inheritdoc}
     */
    public function onKernelController(FilterControllerEvent $event)
    {
        if (!is_array($controllers = $event->getController())) {
            return;
        }

        $request = $event->getRequest();
        $content = $request->getContent();

        list($controller, $methodName) = $controllers;

        $reflectionClass = new \ReflectionClass($controller);
        $classAnnotation = $this->reader
            ->getClassAnnotation($reflectionClass, CheckRequest::class);

        $reflectionObject = new \ReflectionObject($controller);
        $reflectionMethod = $reflectionObject->getMethod($methodName);
        $methodAnnotation = $this->reader
            ->getMethodAnnotation($reflectionMethod, CheckRequest::class);

        if (!($classAnnotation || $methodAnnotation)) {
            return;
        }

        if ($request->getContentType() !== 'json' ) {
            return $event->setController(
                function() {
                    return new JsonResponse(['success' => false]);
                }
            );
        }

        if (empty($content)) {
            throw new BadRequestHttpException('Content is empty');
        }

        $data = json_decode($content, true);

        if ($request->getContentType() !== 'json' ) {
            return $event->setController(
                function() {
                    return new JsonResponse(['success' => false]);
                }
            );
        }
    }
}

请注意,您不是返回响应,而是使用$event->setController();设置整个控制器,并且在拨打电话时也必须return

然后在您的控制器中,您可以在整个班级上设置它:

use AppBundle\Annotation\CheckRequest;

/**
 * @CheckRequest
 */
class YourController extends Controller
{
}

或个别方法/行动:

use AppBundle\Annotation\CheckRequest;

class TestController extends Controller
{
    /**
     * @Route("/", name="index")
     * @CheckRequest
     */
    public function indexAction(Request $request)
    {
        // ...
    }
}

答案 1 :(得分:0)

对于Symfony 3.4。*

public function onKernelController(FilterControllerEvent $event){

    if (!is_array($controllers = $event->getController())) {
        return;
    }

    list($controller, $methodName) = $controllers;

    $reflectionClass = new \ReflectionClass($controller);

    // Controller
    $reader = new \Doctrine\Common\Annotations\AnnotationReader();
    $classAnnotation = $reader->getClassAnnotation($reflectionClass, AnnotationClass::class);

    // Method
    $reflectionMethod = $reflectionClass->getMethod($methodName);
    $methodAnnotation = $reader->getMethodAnnotation($reflectionMethod, AnnotationClass::class);

    if(!($classAnnotation || $methodAnnotation)){
        return;
    }

    /** TODO CODE HERE **/
}