Skip to content

Instantly share code, notes, and snippets.

@flohw
Last active November 6, 2019 12:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save flohw/4efb4e37e2b57dda1e69b35ad9f42db0 to your computer and use it in GitHub Desktop.
Save flohw/4efb4e37e2b57dda1e69b35ad9f42db0 to your computer and use it in GitHub Desktop.
Regrouper des annotations Symfony
<?php
namespace App\Controller;
use App\Rest\Annotations\PaginationParams;
use FOS\RestBundle\Controller\Annotations as FOSRest;
use FOS\RestBundle\Request\ParamFetcherInterface;
class ArticleListController extends AbstractFOSRestController
{
/**
* Ancienne méthode
*
* @FOSRest\QueryParam(name="_page", requirements="\d+", default=1)
* @FOSRest\QueryParam(name="_per_page, requirements="(10|20|50|100)", default=50)
* @FOSRest\QueryParam(name="_sort", requirements="-?[a-zA-Z_]+(\.[a-zA-Z_]+)?", default="id")
*/
public function __invoke(ParamFetcherInterface $paramFetcher)
{
$paramFetcher->get('_page');
$paramFetcher->get('_per_page');
$paramFetcher->get('_sort');
}
/**
* Nouvelle méthode
*
* @PaginationParams()
*/
public function __invoke(ParamFetcherInterface $paramFetcher)
{
$paramFetcher->get('_page');
$paramFetcher->get('_per_page');
$paramFetcher->get('_sort');
}
}
<?php
namespace App\EventListener;
use App\Rest\ParamReader;
use FOS\RestBundle\FOSRestBundle;
use FOS\RestBundle\Request\ParamFetcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\HttpKernel\KernelEvents;
class GlobalParamFetcherSubscriber implements EventSubscriberInterface
{
private $paramFetcher;
private $paramReader;
public static function getSubscribedEvents()
{
return [
KernelEvents::CONTROLLER => 'onKernelController',
];
}
public function __construct(ParamFetcherInterface $paramFetcher, ParamReader $paramReader)
{
$this->paramFetcher = $paramFetcher;
$this->paramReader = $paramReader;
}
public function onKernelController(ControllerEvent $event)
{
$request = $event->getRequest();
if (!$request->attributes->get(FOSRestBundle::ZONE_ATTRIBUTE, true)) {
return;
}
$controller = $event->getController();
if (\is_callable($controller) && method_exists($controller, '__invoke')) {
$controller = [$controller, '__invoke'];
}
$annotations = $this->paramReader->read(new \ReflectionClass($controller[0]), $controller[1]);
foreach ($annotations as $annotation) {
foreach ($annotation->getAnnotationsInstances() as $fosRestAnnotation) {
$this->paramFetcher->addParam($fosRestAnnotation);
}
}
}
}
<?php
namespace App\Rest\Annotations;
use FOS\RestBundle\Controller\Annotations\QueryParam;
/**
* @Annotation
*/
class PaginationParams implements ParamInterface
{
public $defaultSort = 'id';
public function getAnnotationsInstances(): array
{
return [
$this->getPageParam(),
$this->getPerPageParam(),
$this->getSortParam(),
];
}
public function getName(): string
{
return 'pagination';
}
private function getPageParam()
{
$page = new QueryParam();
$page->name = '_page';
$page->requirements = "\d+";
$page->default = 1;
return $page;
}
private function getPerPageParam()
{
$perPage = new QueryParam();
$perPage->name = '_per_page';
$perPage->requirements = '(10|25|50|100)';
$perPage->default = 50;
return $perPage;
}
private function getSortParam()
{
$sort = new QueryParam();
$sort->name = '_sort';
$sort->requirements = '(\-)?[a-zA-Z_]+(\.[a-zA-Z_]+)?';
$sort->default = $this->defaultSort;
return $sort;
}
}
<?php
namespace App\Rest\Annotations;
use FOS\RestBundle\Controller\Annotations\QueryParam;
/**
* @Annotation
*/
class PaginationParams implements ParamInterface
{
public $defaultSort = 'id';
public function getAnnotationsInstances(): array
{
return [
$this->getPageParam(),
$this->getPerPageParam(),
$this->getSortParam(),
$this->getLimitParam(),
];
}
public function getName(): string
{
return 'pagination';
}
private function getPageParam()
{
$page = new QueryParam();
$page->name = '_page';
$page->requirements = "\d+";
$page->default = 1;
return $page;
}
private function getPerPageParam()
{
$perPage = new QueryParam();
$perPage->name = '_per_page';
$perPage->requirements = '(10|25|50|100)';
$perPage->default = 50;
return $perPage;
}
private function getSortParam()
{
$sort = new QueryParam();
$sort->name = '_sort';
$sort->requirements = '(\-)?[a-zA-Z_]+(\.[a-zA-Z_]+)?';
$sort->default = $this->defaultSort;
return $sort;
}
/**
* @deprecated use _per_page parameter instead
*/
private function getLimitParam()
{
$limit = new QueryParam();
$limit->name = 'limit';
$limit->requirements = '(10|25|50|100)';
$limit->default = 50;
return $limit;
}
}
<?php
namespace App\Rest\Annotations;
use FOS\RestBundle\Controller\Annotations\AbstractScalarParam;
interface ParamInterface
{
/**
* @return AbstractScalarParam[]
*/
public function getAnnotationsInstances(): array;
public function getName(): string;
}
<?php
namespace App\Rest;
use App\Rest\Annotations\ParamInterface;
use Doctrine\Common\Annotations\Reader;
use FOS\RestBundle\Request\ParamReaderInterface;
class ParamReader implements ParamReaderInterface
{
private $annotationReader;
public function __construct(Reader $annotationReader)
{
$this->annotationReader = $annotationReader;
}
/**
* @return ParamInterface[]
*/
public function read(\ReflectionClass $reflection, $method)
{
if (!$reflection->hasMethod($method)) {
throw new \InvalidArgumentException(sprintf("Class '%s' has no method '%s'.", $reflection->getName(), $method));
}
$methodParams = $this->getParamsFromMethod($reflection->getMethod($method));
$classParams = $this->getParamsFromClass($reflection);
return array_merge($methodParams, $classParams);
}
public function getParamsFromMethod(\ReflectionMethod $method)
{
$annotations = $this->annotationReader->getMethodAnnotations($method);
return $this->getParamsFromAnnotationArray($annotations);
}
public function getParamsFromClass(\ReflectionClass $class)
{
$annotations = $this->annotationReader->getClassAnnotations($class);
return $this->getParamsFromAnnotationArray($annotations);
}
private function getParamsFromAnnotationArray(array $annotations)
{
$params = [];
foreach ($annotations as $annotation) {
if ($annotation instanceof ParamInterface) {
$params[$annotation->getName()] = $annotation;
}
}
return $params;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment