Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork9.7k
[DependencyInjection] Allow using expressions as service factories#45447
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
nicolas-grekas left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
That is interesting! There are BC concerns we need to consider 🤔
EgAbstractRecursivePass::getConstructor() needs an update now, and classes in the FrameworkBundle's Descriptor namespace also.
jvasseur commentedFeb 16, 2022
Yeah, it might needs a bit of work to finish it, I wasn't really familiar with the DI components internal implementation before starting this PR so I might have missed some things. Concerning the Concerning BC breaks, the only one I see is concerning the typing of the factory property in case someone was writing a compiler pass that doesn't expect to receive an expression object from it. |
61aa6c9 to65ff961Comparejvasseur commentedFeb 18, 2022
I've decided to go with returning the |
nicolas-grekas commentedFeb 21, 2022 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Thinking about all this, what you want to achieve can be done by writing: $services->set(MyServiceInterface::class) ->factory('current') ->arg([expr("env('MY_ENV_VAR') ? service('some_service') : service('some_other_service')")]) If this works already, this proves we don't need to change any interfaces. Instead, we might want to improve the way this can be expressed. |
jvasseur commentedFeb 22, 2022
While working on the feature I thought of a similar workaround with a user defined identity function but it still feels like a hack and having a supported way of doing without any hacks would be better for documentation and discoverability. |
nicolas-grekas commentedFeb 22, 2022 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
It took me a while to figure out an approach that could work, and here it is:#45512 |
nicolas-grekas commentedMar 4, 2022 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Closing in favor of#45512 |
…ce factories (nicolas-grekas, jvasseur)This PR was squashed before being merged into the 6.1 branch.Discussion----------[DependencyInjection] Allow using expressions as service factories| Q | A| ------------- | ---| Branch? | 6.1| Bug fix? | no| New feature? | yes| Deprecations? | yes| Tickets | -| License | MIT| Doc PR | -Replaces#45447This PR allows using expressions as service factories:- in YAML: `factory: '@=service("foo").bar()'`- in PHP: `->factory(expr('service("foo").bar()'))`- in XML: `<factory expression="service('foo').bar()" />`In addition, it allows the corresponding expressions to get access to the arguments of the service definition using the `arg($index)` function and `args` variable inside expressions:```yamlservices: foo: factory: '@=arg(0).baz()' # works also: @=args.get(0).baz() arguments: ['@bar']```Internally, instead of allowing `Expression` objects in `Definition` objects as in#45447, factory expressions are conveyed as a strings that starts with `@=`. This is chosen by taking inspiration from yaml and to not collide with any existing callable.Commits-------c430989 [DependencyInjection] Allow using expressions as service factories
Uh oh!
There was an error while loading.Please reload this page.
This makes it easier to create services base on more complex expressions like for example switching the implementation based on an env variable.
I often find myself having to do this kind of switching and having a way to do it directly in services configuration instead of having to create a factory for it would be great.
I was actually surprise by how small the required patch was to support it.