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, belirli controller methodlarına ulaşabilecekler. Mesela ben sizin methodlardan birine 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 indexAction methoduna ulaşmalarını 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")
*/
class PlayerController extends Controller
{
/**
* @@param Request $request
* @@param string $name
*
* @Method({"GET"})
*
* @Route("/{name}", requirements={"name" = "\w+"})
*
* @Player(names={"Pele", "Zico"}, message="Maradona is unauthorised player.")
*
* @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 ReflectionObject;
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)
{
$controllerReflection = new ReflectionObject($controller[0]);
$methodReflection = $controllerReflection->getMethod($controller[1]);
/** @var Player $playerAnnotation */
$playerAnnotation = $this->reader->getMethodAnnotation($methodReflection, $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