27
votes

I am trying to create a simple bundle inheritance as instructed in here and ran into a problem with routes. I'm using annotations for routing. When I register my child bundle in AppKernel.php all my parent bundles routes are lost.

For what I understand from the documentation Symfony2 should look all files, including routes, first from the child bundle and then from the parent bundle. Now that is not happening, only child bundles controllers seems to be loaded.

In my child bundles Bundle file I have implemented getParent function as instructed, and in my routing.yml I have:

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

which worked fine before the inheritance.

I have tested that the system works fine if in include all controller files separetely in routing.yml but that seems very cumbersome way to make the inheritance to work as I only want to override few parts of the parent bundle ( not all controllers ).

Profiler is showing both of my bundles as active.

4

4 Answers

19
votes

I found the right solution for this issue. Today I was also trying to override a parent bundle configured with annotations routing and also found that parent routes were ignored if the anotation routing imported the whole bundle ("@SomeBundle/Controller").

After a little debugging I found that the explanation for this is that if you use "@" as prefix for the controller this will pass to the kernel resolver which will return ONLY the child resource if the parent resource has been overridden. So the solution is to provide the full path of the bundle, considering that the kernel will try to match the resource from app/Resources so you will have to add a relative directory (../../) before the actual path:

# 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

This will work as expected: all parent routes will be imported and will be overridden by all routes specified in the child bundle.

10
votes

In addition to previous answer, I also had to change the name of the routing.yml of the child bundle (e.g. to routing_child.yml) to get it working. I assume this is because Symfony totally ignores the parent bundle routing file if the name is identical.

EDIT: In many cases it's also practical to import parent bundle routes into the child bundle routing file like this:

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

The official documentation says that you shall just copy parent routing file to your child bundle:

The easiest way to "override" a bundle's routing is to never import it at all. Instead of importing a third-party bundle's routing, simply copying that routing file into your application, modify it, and import it instead.

Also, you cannot include parent's bundle routing file using symbolic names "@ParentBundle" because this name is resolved to "@ChildBundle".

If you really want to include parent routes file, then you shall use the absolute path to that file or path relative to current directory, i.e.:

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

or

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

Another workaround is to symlink your parent routing file into your child bundle and include it with shorter path, i.e.:

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

and then

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

P.S. I hope they'll find some better and less uglier way to override and extend routing from parent bundle, but now we have to se some of those ugly workarounds.

0
votes

With bundle inheritance, you can override the parent bundle's files.

If you create a routing file in the same location as the parents in your bundle (if the routing of the parent file is at ParentBundle/Resources/config/routing.yml, and you create a routing file at ChildBundle/Resources/config/routing.yml), it will override the parent's routing.yml, and symfony will only use the child's routing.yml.

I haven't tried, but if you import the parent bundle's routing.yml in the child bundle's routing.yml, you can solve your problem. As Symfony router will always choose the first matching route it finds, you can override the specific route you want by writing the relevant routing code on top of the import code.