Symfony2 Аннотация Наследование

В моем проекте у меня есть класс BaseController, который реализует несколько методов, используемых всеми моими контроллерами.

Теперь я хотел добавить @QueryParam для этого базового класса. Мой класс выглядит так:

class DoctrineRESTQueryController extends FOSRestController
{
/**
* @QueryParam(name="start",default=0)
* @QueryParam(name="limit",default=null)
*/
public function getQueryResponseAction (ParamFetcher $paramFetcher) {

}
}

Теперь у меня есть фактический контроллер, который выходит из моего базового контроллера:

class DefaultController extends DoctrineRESTQueryController {

/**
* Retrieves all SI Prefixes in the database
*
* @Routing\Route("/siprefix", defaults={"method" = "get","_format" = "json"})
* @Routing\Method({"GET"})
* @ApiDoc(output="array<PartKeepr\SiPrefixBundle\Entity\SiPrefix>")
*
* @View()
*
* {@inheritdoc}
*/
public function getQueryResponseAction(ParamFetcher $paramFetcher) {
$paramFetcher->get("start");
}
}

К сожалению, Symfony2, по-видимому, не наследует аннотации @QueryParam от суперкласса, потому что вызов $ paramFetcher-> get («start») приводит к исключению «Нет @ QueryParam / @ RequestParam конфигурации для параметра ‘start'».

Есть ли способ заставить наследование аннотаций работать или любое другое решение, чтобы мне не нужно было добавлять @QueryParam к каждому из моих контроллеров?

5

Решение

Там нет функции в FosRestBundle для этого, поэтому вы должны переопределить его части для того, что вам нужно, более конкретно метод getParamsFromMethod в классе FOSRestBundle/Request/ParamReader (увидеть Исходный код здесь).

Это можно сделать с помощью наследования пакетов.

Во-первых, подкласс FOSRestBundle\Request\ParamReader в одной из ваших связок, например YourSite\RestBundle\Request\MyParamReader и переопределить getParamsFromMethod загрузив аннотации родительского метода и объединив их с аннотациями текущего:

namespace YourSite\RestBundle\Request\MyParamReader;

use FOSRestBundle\Request\ParamReader;

class MyParamReader extends ParamReader
{
public function getParamsFromMethod(\ReflectionMethod $method)
{
$parentParams = array();
$params = parent::getParamsFromMethod($method);

// This loads the annotations of the parent method
$declaringClass = $method->getDeclaringClass();
$parentClass = $declaringClass->getParentClass();

if ($parentClass && $parentClass->hasMethod($method->getShortName())) {
$parentMethod = $parentClass->getMethod($method->getShortName());
$parentParams = parent::getParamsFromMethod($parentMethod);
}

return array_merge($params, $parentParams);
}
}

При необходимости вы можете изменить код для обработки иерархий глубокого наследования.

Теперь вы должны сказать FOSRestBundle использовать свой YourSite\RestBundle\Request\MyParamReader класс вместо FOSRestBundle\Request\ParamReader, Вам необходимо переопределить определение службы, где средство чтения параметров указано как зависимость. Это где переопределение / наследование связки вступает в игру, смотрите эта статья Symfony2.

Определение сервиса находится в Resources/config/request.xml файл (см. Исходный код здесь), FOSRestBundle\Request\ParamReader это зависимость FOS\RestBundle\Request\ParamFetcher,

Таким образом, вы должны переопределить Resources/config/request.xml файл. Для этого, следуя приведенной выше статье, зарегистрируйте свой пакет и объявите FOSRestBundle как его родитель:

namespace YourSite\RestBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class YourSiteRestBundle extends Bundle
{
public function getParent()
{
return 'FOSRestBundle';
}
}

Создать файл YourSite\RestBundle\Resources\config\request.xml добавить YourSite\RestBundle\Request\MyParamReader как зависимость:

<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters>
<parameter key="fos_rest.request.param_fetcher.class">FOS\RestBundle\Request\ParamFetcher</parameter>
<parameter key="your_site_rest.request.param_fetcher.reader.class">YourSite\RestBundle\Request\MyParamReader</parameter>
</parameters>
<services>
<service id="fos_rest.request.param_fetcher" class="%fos_rest.request.param_fetcher.class%" scope="request">
<argument type="service" id="your_site.request.param_fetcher.reader"/>
<argument type="service" id="request"/>
<argument type="service" id="fos_rest.violation_formatter"/>
<argument type="service" id="validator" on-invalid="null"/>
</service>
<service id="your_site.request.param_fetcher.reader" class="%your_site_rest.request.param_fetcher.reader.class%">
<argument type="service" id="annotation_reader"/>
</service>
</services>
</container>

Это не проверено, но это должно работать.

5

Другие решения

Отличное решение, спасибо! Может быть, кто-то ищет такую ​​же конфигурацию .yml в symfony3, должно работать следующее:

parameters:
fos_rest.request.param_fetcher.class: FOS\RestBundle\Request\ParamFetcher
your_site_rest.request.param_fetcher.reader.class: YourSiteBundle\Request\MyParamReader

services:
fos_rest.request.param_fetcher:
class: %fos_rest.request.param_fetcher.class%
arguments: ['@service_container', '@your_site.request.param_fetcher.reader', '@request_stack', '@?validator']
scope: request
your_site.request.param_fetcher.reader:
class: %your_site.request.param_fetcher.reader.class%
arguments: ['@annotation_reader']
0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector