繁体   English   中英

Symfony2注释继承

[英]Symfony2 Annotation Inheritance

在我的项目中,我有一个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”)的调用会导致异常“参数'start'的@ QueryParam / @ RequestParam配置”。

有什么方法可以使注释继承起作用,或者有其他解决方案,所以我不必在每个控制器中都添加@QueryParam?

FosRestBundle没有FosRestBundle提供的功能,因此您必须根据需要覆盖它的某些部分,更具体地说,是FOSRestBundle/Request/ParamReader类中的getParamsFromMethod方法(请参见此处的源代码 )。

这可以通过捆绑继承来完成。

首先,子类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\\ParamReaderFOS\\RestBundle\\Request\\ParamFetcher的依赖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>

这未经测试,但应该可以。

很好的解决方案,谢谢! 也许有人在symfony3中寻找相同的.yml配置,以下方法应该可以工作:

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']

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM