Symfony 2 is used for large projects with long term support. These projects usually contain many bundles and the bundles depend on one another. The best option is when bundle A is using features of bundle B, but bundle B is not using features of bundle A (unfortunately, it is not always possible). In this case you can easily outsource some bundles.
Example: you have AcmeBundle and CoreBundle. And in CoreBundle you have main layout. Let us say you have counter on each page and it is located in the layout. To implement this feature you could’ve thought of some of the ways below:
- Put calculation counter right in the CoreBundle.
- Create twig block and pass the calculated in AcmeBundle value into template.
In the first approach CoreBundle gets hard dependency from AcmeBundle and the principle of single responsibility is being ruined.
In the second approach you will have to call the same method in each action. You can also create base controller and extend all the applications’ controllers from it, but it does’t fit in the Symfony’s philosophy.
I suggest choosing a different solution, based on using Symfony2 event dispatcher.
Analyzing the Twig and FrameworkBundle source code form the Symfony2 package we can conclude, that we don’t have a pre-render event before rendering template out of box. That means we should add a pre-render event in our application.
Rendering life cycle in SF2 goes the following way. When you call $this->render(), it passes control to DelegatingEngine — which is an abstract rendering engine. Based on the tamplate name \Symfony\Component\Templating\DelegatingEngine passes control to \Symfony\Bridge\Twig\TwigEngine, \Symfony\Component\Templating\PhpEngine or your own custom template engine (that implements \Symfony\Bundle\FrameworkBundle\Templating\EngineInterface).
First, you have to decide what events do you need and create class, that describes events.
Then you need to describe event class, that was raised:
Now let’s extend base class DelegatingEngine and add events support:
Finally, config your classes, open services.yml and add the following lines:
That’s all, now create an EventListener in you AcmeBundle and register it in the service container
As a result you have more independent from one another bundles.