Symfony2绑定继承丢失父绑定路由


Symfony2 bundle inheritance losing parent bundles routes

我正试图按照此处的指示创建一个简单的bundle继承,但遇到了路由问题。我正在使用批注进行路由。当我在AppKernel.php中注册我的子捆绑包时,我所有的父捆绑包路由都会丢失。

根据我从文档中了解到的情况,Symfony2应该先查看子捆绑包中的所有文件,包括路由,然后再查看父捆绑包。现在这种情况还没有发生,似乎只加载了子捆绑控制器。

在我的子捆绑包Bundle文件中,我按照指示实现了getParent函数,在我的routing.yml中,我有:

ParentBundle:
resource: "@Parent/Controller/"
type:     annotation
prefix:   /admin/

在继承之前运作良好。

我已经测试过,如果在routing.yml中单独包含所有控制器文件,系统会正常工作,但这似乎是一种非常麻烦的继承方式,因为我只想覆盖父捆绑包的几个部分(而不是所有控制器)。

Profiler显示我的两个捆绑包都处于活动状态。

我找到了这个问题的正确解决方案。今天,我还试图覆盖用注释路由配置的父捆绑包,还发现如果anotation路由导入了整个捆绑包("@SomeBundle/Controller"),则会忽略父路由。

经过一点调试,我发现对此的解释是,如果你使用"@"作为控制器的前缀,它将传递给内核解析器,如果父资源被重写,内核解析器将只返回子资源。因此,解决方案是提供捆绑包的完整路径,考虑到内核将尝试匹配app/Resources中的资源,因此您必须在实际路径之前添加一个相对目录(../../):

# app/config/routing.yml:
some_parent:
    resource: "../../src/Application/ParentBundle/Controller"
    type: annotation
# ChildBundle implements getParent() method to inherit from ParentBundle
some_child:
    resource: "@ChildBundle/Controller"
    type: annotation

这将按预期工作:所有父路由都将被导入,并将被子捆绑包中指定的所有路由覆盖。

除了前面的答案,我还必须更改子捆绑包的routing.yml的名称(例如,更改为routing_child.yml)才能使其工作。我认为这是因为如果名称相同,Symfony会完全忽略父捆绑包路由文件。

编辑:在许多情况下,将父捆绑包路由导入子捆绑包路由文件也是可行的,如下所示:

# routing_child.yml     
_parent:
    resource: "@MyParentBundle/Resources/config/routing.yml"

官方文档规定,您只需将父路由文件复制到您的子捆绑包:

"覆盖"捆绑包路由的最简单方法是从不导入它。不必导入第三方捆绑包的路由,只需将该路由文件复制到应用程序中,然后修改并导入即可。

此外,您不能使用符号名称"@ParentBundle"包含父捆绑包路由文件,因为此名称已解析为"@ChildBundle"。

如果你真的想包括父路由文件,那么你应该使用该文件的绝对路径或相对于当前目录的路径,即:

# @YourChildBundle/Resources/routing.yml
YourParentBundle:
  resource: "/srv/www/example.com/src/Your/ParentBundle/Resources/routing.yml"

# @YourChildBundle/Resources/routing.yml
YourParentBundle:
  resource: "../../../../../Your/ParentBundle/Resources/routing.yml"

另一种解决方法是将父路由文件符号链接到子捆绑包中,并将其包含在较短的路径中,即:

cd YourChildBunde
ln -s ../../../../../Your/ParentBundle/Resources/routing.yml parent_routes.yml

然后

# @YourChildBundle/Resources/routing.yml
YourParentBundle:
  resource: "parent_routing.yml"

附言:我希望他们能找到一些更好、不那么丑陋的方法来覆盖和扩展父捆绑包中的路由,但现在我们必须找到一些丑陋的解决方案。

通过bundle继承,您可以覆盖父bundle的文件。

如果您在与捆绑包中的父文件相同的位置创建路由文件(如果父文件的路由位于ParentBundle/Resources/config/routing.yml,并且您在ChildBundle/Reresources/config/rooting.yml创建路由文件),它将覆盖父文件的routing.yml。symfony将仅使用子文件的routin.yml。

我还没有尝试过,但如果你在子捆绑包的routing.yml中导入父捆绑包的outing.yml,你就可以解决你的问题。由于Symfony路由器总是会选择它找到的第一个匹配路由,因此您可以通过在导入代码上写入相关的路由代码来覆盖您想要的特定路由。