简体   繁体   中英

How to access services on bundle load in Symfony2?

I'd really like to know how to access services (like doctrine, twig, etc) from inside the Bundle->build(ContainerBuilder) method.

Basically, the problem is that I need a menu system that bundles can add menu items to, without needing to have them hard-coded in a template somewhere. To that end, I figured that a service-based menu would work nicely (so I've made a menu builder service which works for testing purposes in a controller).

From what I can tell, I can't do it in the controller because the controller is only loaded when it's needed, where I will have multiple bundles that need to add menu items, whether their controllers are being used or not. In fact, the menu items are more important when they AREN'T in use for site navigation.

I figured it would probably have something to do with the Bundle->build method. It seems like the ContainerBuilder->get should allow me to get services, but there is only the service_container service in that (as shown by getServiceIds). When I ContainerBuilder->get('service_container')->getServiceIds , again the only service is service_container.

My thought now is that when the bundle is "built", the services aren't loaded.

Is there something I'm missing? Some overridable method, some event to listen in on?

This is a perfect use case for Symfony's event listener/dispatch component.

Rather than trying to pass around items from the service container to places they don't belong, like bundle initializer methods, have your menu builder class send out events using Symfony's event_dispatcher service. When it is building its menu, just add the @event_dispatcher service as a dependency:

services:
    acme_bundle.menu_builder:
        class: Acme\AcmeBundle\Menu\MenuBuilder
        arguments: [@event_dispatcher]

Then, in your MenuBuilder class, use the EventDispatcher to send out events:

class MenuBuilder
{
    private $dispatcher;

    public function __construct(EventDispatcherInterface $dispatcher)
    {
        $this->dispatcher = $dispatcher;
    }

    /**
     * Main function for building menus and dispatching related events.
     */
    public function buildMenu()
    {
        $menu = new Menu();
        $event = new MenuEvent('acme_bundle.event_name', $menu);
        $this->dispatcher->dispatch($event);

        return $menu;
    }
}

Other bundles can register as listeners to the event, and add menu items to the menu:

services:
    acme_bundle.configure_menu_listener:
        class: Acme\OtherBundle\Listener\ConfigureMenuListener
        tags:
            - { name: kernel.event_listener, event: 'acme_bundle.event_name', method: configureMenu }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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