I'm writing a Symfony application. Means: The application has a structure of a Symfony application and uses Symfony's MVC (symfony/http-kernel
, symfony/routing
etc.), but it should be as framework-independent as possible. So instead of the framework's DI, I'm using PHP-DI.
Now I've added the symfony/event-dispatcher
component and to register a listener for all custom events.
services.yaml
system.event_handler:
tags:
- { name: system.event_handler, event: general.user_message_received, method: handle }
- { name: system.event_handler, event: xxx.foo, method: handle }
- { name: system.event_handler, event: yyy.foo, method: handle }
- { name: system.event_handler, event: zzz.foo, method: handle }
The system.event_handler
is defined in my PHP-DI dependencies file:
...
EventHandlerInterface::class => DI\factory(function(ContainerInterface $container) {
return new SystemEventHandler(
$container->get('process_handler.xxx'),
$container->get('process_handler.yyy'),
$container->get('process_handler.zzz')
);
}),
'system.event_handler' => DI\get(EventHandlerInterface::class),
...
Now I'm getting an error:
RuntimeException
The definition for "system.event_handler" has no class. If you intend to inject this service dynamically at runtime, please mark it as synthetic=true. If this is an abstract definition solely used by child definitions, please add abstract=true, otherwise specify a class to get rid of this error.
Why? Is it wrong to use an alias at this paces?
OK, I've replaced the alias in the services.yaml
by the FQCN of my event handler:
App\Process\SystemEventHandler:
tags:
- { name: system.event_handler, event: general.user_message_received, method: handle }
- { name: system.event_handler, event: xxx.foo, method: handle }
- { name: system.event_handler, event: yyy.foo, method: handle }
- { name: system.event_handler, event: zzz.foo, method: handle }
No errors anymore. But the event handler is still not get added to the EventDispatcher
.
How to register event listeners (defined in the PHP-DI container) in Symfony 4?
PHP-DI is called as a fallback of Symfony's container. So when an entry is not defined in Symfony, it is pulled out of PHP-DI. However I've never tried defining an entry in both containers, from my POV (as the maintainer of PHP-DI) this is not supposed to work.
Since you need to use Symfony tags, the simplest solution is to define that specific service entirely in Symfony's config (not PHP-DI).
Another lead could be to try to write a Symfony compiler pass to try and make this work, but I don't know if that is feasible. If you manage to find a good solution please report it in the GitHub repository, we could try to integrate it.