Custom annotation in symfony 3 controller Custom annotation in symfony 3 controller symfony symfony

Custom annotation in symfony 3 controller


You need to make a custom annotation and then a listener that injects the annotation reader and handles the kernel.controller event:

Annotation

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

Service Definition

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

Listener:

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]);                }            );        }    }}

Notice that instead of returning the response, you set the entire controller with $event->setController();, and you also must return when making that call.

Then in your controller you can set it on the entire class:

use AppBundle\Annotation\CheckRequest;/** * @CheckRequest */class YourController extends Controller{}

or individual methods/actions:

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


For 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 **/}