Hello everyone!

We have been investing plenty of personal time and energy for many years to share our knowledge with you all. However, we now need your help to keep this blog running. All you have to do is just click one of the adverts on the site, otherwise it will sadly be taken down due to hosting etc. costs. Thank you.

This example shows us how we create a custom annotation for constollers and their methods. The annotation we will create is called @Model and it has three properties as shown below.


Annotation class


declare(strict_types=1);

namespace App\Annotation;

/**
* @Annotation
*/
class Model
{
/**
* @var string
*/
public $namespace;

/**
* @var int
*/
public $version;

/**
* @var array
*/
public $types;
}

Model class


This is optional.


declare(strict_types=1);

namespace App\Model;

class Country
{
// Whatever
}

Controller


declare(strict_types=1);

namespace App\Controller;

use App\Annotation\Model;
...

/**
* @Route("/countries")
* @Model
*/
class CountryController
{
/**
* @Route(....)
* @Model(
* namespace="App\Model\Country",
* version=1,
* types={"json","xml"}
* )
*/
public function getAll(): Response
{
// ...
}
}

ModelAnnotationListener


declare(strict_types=1);

namespace App\Event\Listener;

use App\Annotation\Model as ModelAnnotation;
use Doctrine\Common\Annotations\Reader;
use ReflectionClass;
use ReflectionException;
use RuntimeException;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;

class ModelAnnotationListener
{
private $annotationReader;

public function __construct(Reader $annotationReader)
{
$this->annotationReader = $annotationReader;
}

public function onKernelController(FilterControllerEvent $event): void
{
if (!$event->isMasterRequest()) {
return;
}

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

$this->handleAnnotation($controllers);
}

private function handleAnnotation(iterable $controllers): void
{
list($controller, $method) = $controllers;

try {
$controller = new ReflectionClass($controller);
} catch (ReflectionException $e) {
throw new RuntimeException('Failed to read annotation!');
}

$this->handleClassAnnotation($controller);
$this->handleMethodAnnotation($controller, $method);
}

private function handleClassAnnotation(ReflectionClass $controller): void
{
$annotation = $this->annotationReader->getClassAnnotation($controller, ModelAnnotation::class);

if ($annotation instanceof ModelAnnotation) {
print_r($annotation);
}
}

private function handleMethodAnnotation(ReflectionClass $controller, string $method): void
{
$method = $controller->getMethod($method);
$annotation = $this->annotationReader->getMethodAnnotation($method, ModelAnnotation::class);

if ($annotation instanceof ModelAnnotation) {
print_r($annotation);
}
}
}

services:
_defaults:
autowire: true
autoconfigure: true
public: false

App\Event\:
resource: '../../src/Event'

App\Event\Listener\ModelAnnotationListener:
tags:
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController }


Result


App\Annotation\Model Object
(
[namespace] =>
[version] =>
[types] =>
)

App\Annotation\Model Object
(
[namespace] => App\Model\Country
[version] => 1
[types] => Array
(
[0] => json
[1] => xml
)
)