So the question is pretty straightforward. I have a code in my controller that has became redundant, and i've decided to make the annotation for it.
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));
}
How do i make custom annotation @CheckRequest in which I can use the $request object as a parameter?
You need to make a custom annotation and then a listener that injects the annotation reader and handles the kernel.controller event:
/**
 * @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]);
                }
            );
        }
    }
}
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)
    {
        // ...
    }
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With