在我的项目中,我有一个 BaseController 类,它实现了我所有 Controller 使用的几种方法。
现在我想为该基类添加@QueryParam。我的类(class)看起来像这样:
class DoctrineRESTQueryController extends FOSRestController
{
/**
* @QueryParam(name="start",default=0)
* @QueryParam(name="limit",default=null)
*/
public function getQueryResponseAction (ParamFetcher $paramFetcher) {
}
}
现在我有了从基本 Controller 扩展而来的实际 Controller :
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 似乎没有从父类(super class)继承@QueryParam 注释,因为调用$paramFetcher->get("start") 导致异常“No @QueryParam/@RequestParam configuration for parameter 'start '”。
有没有什么方法可以使注解继承起作用,或者有任何其他解决方案,这样我就不必将@QueryParam 添加到我的每个 Controller 中了吗?
最佳答案
FosRestBundle
中没有这方面的功能,因此您必须根据需要重写它的一部分,更具体地说是类 FOSRestBundle/中的方法
(参见 source code here)。getParamsFromMethod
请求/ParamReader
这可以通过包继承来完成。
首先,子类 FOSRestBundle\Request\ParamReader
在你的一个 bundle 中,例如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
。您需要覆盖服务定义,其中参数读取器被列为依赖项。这是包覆盖/继承发挥作用的地方,请参阅 this Symfony2 article .
服务定义位于Resources/config/request.xml
文件中(参见source code here),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>
这是未经测试的,但它应该有效。
关于php - Symfony2 注释继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30425978/