Search code examples
symfonysymfony-dependency-injection

How does Symfony find AsEventListener classes?


I have found a $container->registerAttributeForAutoconfiguration call here but as far as I can tell this does not add classes to the container. Yet the documentation says

An alternative way to define an event listener is to use the AsEventListener PHP attribute. This allows to configure the listener inside its class, without having to add any configuration in external files.

I thought maybe it does something to the ContainerConfigurator? grep -h -i eventlistener $(ag -l configurator)|grep -v '^use' I see nothing relevant.

So where can I find the code which adds these classes to the container?


Solution

  • The classes are "found" by the general "services" configuration. There is nothing specific about this attribute for making classes available as services in Symfony.

    E.g., on a default Symfony installation:

    # config/services.yaml
    services:
        # default configuration for services in *this* file
        _defaults:
            autowire: true      # Automatically injects dependencies in your services.
            autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
    
        # makes classes in src/ available to be used as services
        # this creates a service per class whose id is the fully-qualified class name
        App\:
            resource: '../src/'
            exclude:
                - '../src/DependencyInjection/'
                - '../src/Entity/'
                - '../src/Kernel.php'
    

    This tells Symfony to look for everything under src, barring the three listed exclusions.

    The class ultimately responsible for finding and loading these files is Symfony\Component\DependencyInjection\Loader\FileLoader. Check the findClasses and registerClasses methods.

    The code you found on FrameworkExtension, tells Symfony what to do each time a class marked with the #[AsEventListener] attribute is found: to be tagged kernel.event_listener (unless the tag was used on a method, in which case it throws an exception).

    Later on, in RegisterListenersPass, the services that were previously tagged as kernel.event_listener (either via this attribute or any other way), are registered as event listeners.