[DependencyInjection] Service subscriber without autowire #60272
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
TL;DR
We needed to use the ServiceSubscriber feature in a reusable Bundle.
The best practices for Bundles is to not use the Autowire feature.
But the way service subscriber are registered / resolved only works with autowired services at the moment.
The goal of this PR is to provide a way to easily extract the Locator for a service subscriber class / definition and use it in a custom compiler pass for example.
More details
RegisterServiceSubscribersPass
if the service definition has thecontainer.service_subscriber
getSubscribedServices
static method to cerate a$serviceMap
container.service_subscriber.locator
with the id of the service locatorPsrContainerInterface
ResolveServiceSubscribersPass
which clears tags + inject the locatorThere is mo way to insert a compiler pass in between those two, they have the same priority in the same PassConfig type.
Apart from re-doing all the logic ourselves, there are no easy way to create a service locator solely based on the interface.
Why do I need to use a ServiceSubscriber in my Bundle ?
Our bundle provides extension points, allowing developers to create their own services that integrate seamlessly with the bundle's internal logic. This improves the developer experience (DX) by simplifying service wiring.
Since we can't predict in advance which services these extensions will depend on, using a ServiceSubscriber is ideal. It allows us to support dynamic dependencies without requiring developers to write a compiler pass.
For example, if a developer adds a trait like TwigAwareTrait to a class, the twig service becomes a dependency. We want to give them the flexibility to inject such additional services—beyond those provided by default in the service locator—in a clean and declarative way.