Bildiğimiz gib controller içinde kullanabileceğimiz "Method", "Route" vb. annotationlar var. Bu örneğimizde kendimize özgü kişisel bir tane annotation yaratacağız. Sadece belirtilen kişiler, controller içindeki tüm methodlara ulaşabilecekler. Mesela ben sizin bu methodlara ulaşmanızı engellemek istersem, isminizi annotation içinde listelemeyeceğim. Örnek bu kadar basit!


Config.yml


parameters:
player_names:
- Pele
- Zico
- Maradona
player_annotation_namespace: "Application\\FrontendBundle\\Annotation\\Player"

Player annotation


namespace Application\FrontendBundle\Annotation;

/**
* @Annotation
*/
class Player
{
/**
* @var array
*/
public $names = [];

/**
* @var string
*/
public $code = 403;

/**
* @var string
*/
public $message = 'Unauthorised player.';
}

PlayerController


Aşağıdaki @Player annotation ayarlarına göre, ben sadece "Pele" ve "Zico" ismindeki kişilerin bu controller içindeki tüm methodlara ulaşabilmelerini sağlayacağım. Bununlar birlikte yukarıdaki "Player" classında belirtilen ve varsayılan olarak atanan Unauthorised player. mesajını, annotation içinde Maradona is unauthorised player. olarak değiştireceğim ama koda dokunmayacağım.


namespace Application\FrontendBundle\Controller;

use Application\FrontendBundle\Annotation\Player;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
* @Route("player", service="application_frontend.controller.player")
*
* @Player(names={"Pele", "Zico"}, message="Maradona is unauthorised player.")
*/
class PlayerController extends Controller
{
/**
* @@param Request $request
* @@param string $name
*
* @Method({"GET"})
*
* @Route("/{name}", requirements={"name" = "\w+"})
*
* @return Response
*/
public function indexAction(Request $request, $name)
{
$country = $request->query->get('country', 'none');

return new Response(sprintf('%s is from %s national football team.', $name, $country));
}
}

AnnotationListener


namespace Application\FrontendBundle\Listener;

use Application\FrontendBundle\Annotation\Player;
use Doctrine\Common\Annotations\Reader;
use ReflectionClass;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Routing\Exception\MissingMandatoryParametersException;

class AnnotationListener
{
private $reader;
private $playerNames;
private $playerAnnotationNamespace;

public function __construct(
Reader $reader,
array $playerNames,
$playerAnnotationNamespace
) {
$this->reader = $reader;
$this->playerNames = $playerNames;
$this->playerAnnotationNamespace = $playerAnnotationNamespace;
}

public function onKernelController(FilterControllerEvent $event)
{
$controller = $event->getController();
if (!is_array($controller) || !$event->isMasterRequest()) {
return;
}

$player = $this->getPlayer($event->getRequest());

$this->validatePlayer($controller, $player);
}

private function getPlayer(Request $request)
{
$routeParams = $request->attributes->get('_route_params');
if (!is_array($routeParams)) {
throw new BadRequestHttpException('Invalid request.');
}

if (!isset($routeParams['name'])) {
throw new MissingMandatoryParametersException('Missing name parameter.');
}

return $routeParams['name'];
}

private function validatePlayer(array $controller, $player)
{
/** @var Player $playerAnnotation */
$playerAnnotation = $this->reader->getClassAnnotation(
new ReflectionClass($controller[0]),
$this->playerAnnotationNamespace
);

if (!in_array($player, $playerAnnotation->names)) {
throw new BadRequestHttpException($playerAnnotation->message, null, $playerAnnotation->code);
}
}
}

Listeners.yml


services:
application_frontend.listener.annotation:
class: Application\FrontendBundle\Listener\AnnotationListener
arguments:
- @annotation_reader
- %player_names%
- %player_annotation_namespace%
tags:
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController }

Testler


Geçerli


# Request
GET http://football.dev/app_dev.php/player/Pele?country=Brazil

# Response
200 OK
Pele is from Brazil national football team.

Geçerli


# Request
GET http://football.dev/app_dev.php/player/Zico?country=Brazil

# Response
200 OK
Zico is from Brazil national football team.

Geçersiz


# Request
GET http://football.dev/app_dev.php/player/Maradona?country=Argentina

# Response
400 Bad Request
Maradona is unauthorised player.
400 Bad Request - BadRequestHttpException