Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8907913
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 15, 20262026-06-15T03:02:21+00:00 2026-06-15T03:02:21+00:00

I have a class which is used to generate navigation from a variety of

  • 0

I have a class which is used to generate navigation from a variety of interconnected bundles. I have a Navigation service to accomplish this.

In order to connect this service with the other bits of Navigation, I want to allow the other bundles to define their own services which then listen to the event listener and add their navigation items at the proper time.

The problem is, I can’t figure out how to have a service listen to an event without first calling that service manually in order to create it.

Any ideas?


To give a more concrete idea, I have something like this:

// Set up as a service in the bundle.
class Navigation {
    // ...
    protected $dispatcher; // event dispatcher passed in to service

    // ...
    public function generateNavigation() {
        $items = array();
        // add some items

        $event = new NavigationEvent($items); // custom event
        $this->eventDispatcher->dispatchEvent('navigation_event', $event);
    }
}

// Set up as a service in some secondary bundle.
class NavigationWorker {
    /**
     * @param $dispatcher Same instance as Navigation
     */
    public function __construct(EventDispatcher $dispatcher) {
        $dispatcher->addListener('navigation_event', array($this, 'doSomething'));
    }
}

With this set up, it should work if the NavigationWorker is called at some point and is constructed, but I can’t always call them directly, so it is never constructed and the listener is never added.

The way I currently do it is to pass all of the NavigationWorkers to Navigation and have it add their listener, but this is very ugly.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-15T03:02:23+00:00Added an answer on June 15, 2026 at 3:02 am

    I’m changing the answer to this because while that set me on the right path, it wasn’t the complete answer. That article really only allows you to hook in to pre-defined kernel events. I however needed my own, so I started working back from there.

    In the end, I ended up creating my own tags, a compiler pass to process those tasks. I also added my own extension of EventDispatcher, though that wasn’t super-necessary (you could just use the normal one).

    Here is what the file solution looked like.

    Configuration:

    parameters:
        my_bundle.navigation.event.class: My\Bundle\DependencyInjection\NavigationEvent
    
        my_bundle.event_dispatcher.class: My\Bundle\DependencyInjection\EventDispatcher
        my_bundle.navigation.class: My\Bundle\DependencyInjection\NavigationGenerator
        my_bundle.navigation_listener1.class: My\Bundle\DependencyInjection\NavigationListener
        my_bundle.navigation_listener2.class: My\Bundle\DependencyInjection\NavigationListener
    
    services:
        my_bundle.event_dispatcher:
            class: %my_bundle.event_dispatcher.class%
        my_bundle.navigation:
            class: %my_bundle.navigation.class%
            arguments:
                - @my_bundle.event_dispatcher
        my_bundle.navigation_listener1.class:
            class: %my_bundle.navigation_listener1.class%
            tags:
                - { name: my_bundle.event_listener, event: my_bundle.navigation.generate, method: onGenerateNavigation }
        my_bundle.navigation_listener2.class:
            class: %my_bundle.navigation_listener2.class%
            tags:
                - { name: my_bundle.event_listener, event: my_bundle.navigation.generate, method: onGenerateNavigation }
    

    CompilerPass:

    use Symfony\Component\DependencyInjection\ContainerBuilder;
    use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
    use Symfony\Component\DependencyInjection\Reference;
    
    class EventListenerCompilerPass implements CompilerPassInterface
    {
        public function process(ContainerBuilder $container)
        {
            if (!$container->hasDefinition('my_bundle.event_dispatcher')) {
                return;
            }
    
            $definition = $container->getDefinition(
                'my_bundle.event_dispatcher'
            );
    
            $taggedServices = $container->findTaggedServiceIds(
                'my_bundle.event_listener'
            );
    
            foreach ($taggedServices as $id => $tagAttributes) {
                foreach ($tagAttributes as $attributes) {
                    $definition->addMethodCall(
                        'addListener',
                        array($this->getEventString($attributes['event'], $container),     array(new Reference($id), $attributes['method']))
                    );
                }
            }
        }
    
    protected function getEventString($str, ContainerBuilder $container)
    {
        preg_match('/(.*)\.([^.]*)$/', $str, $matches);
        $parameterName = $matches[1];
        $constName = strtoupper($matches[2]);
    
        $eventClass = $container->getParameter($parameterName . '.event.class');
    
        if (!$eventClass) {
            throw new Exception('Unable to find parameter: ' . $eventClass . '.event.class');
        }
    
        // Return the value of the constant.
        return constant($eventClass . '::' . $constName);
    }
    

    Add a function like this to your compiler class (something like MyBundleBundle).

    public function build(ContainerBuilder $container)
    {
        parent::build($container);
    
        $container->addCompilerPass(new EventListenerCompilerPass());
    }
    

    Now the EventListener will have added listeners for each of those events. You than just implement everything else exactly as you would expect (Navigation dispatches events which it listens too). You can than hook in new event listeners from any bundle, and they don’t even need to share a common class/interface.

    This also works for any custom event, as long as the object which has the constant for the event is registered in the parameters with “.event.class” at the end (so my_bundle.navigation.generate looks for the parameter my_bundle.navigation.event.class, uses that class and the constant GENERATE).

    Hopefully that’ll help anyone else looking to do something similar.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have this vendor-supplied TLB file, which I've used to generate a Ruby proxy
I have a singleton class which is being used throughout the app. I am
I have a class which contains a static collection that can be used across
I have a library which has a basic class which is used extensively by
I have a file attachment class (FileAttachment) which is used in several other classes.
Let's say I have a list in a class which will be used in
I have a silly, little class FileSystemSize which can be used both as an
I have class A which extends the Activity class. This class is in package
I have a base class which has an embedded List that can be used
I have a class that would normally just generate factory objects, however this class

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.