Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[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

Closed
jvasseur wants to merge1 commit intosymfony:6.1fromjvasseur:expr-factory

Conversation

@jvasseur
Copy link
Contributor

@jvasseurjvasseur commentedFeb 16, 2022
edited
Loading

QA
Branch?6.1
Bug fix?no
New feature?yes
Deprecations?no
Tickets
LicenseMIT
Doc PRsymfony/symfony-docs#16516

This makes it easier to create services base on more complex expressions like for example switching the implementation based on an env variable.

namespaceSymfony\Component\DependencyInjection\Loader\Configurator;useApp\MyServiceInterface;returnfunction(ContainerConfigurator$configurator) {$services =$configurator->services();$services->set(MyServiceInterface::class)        ->factory(expr("env('MY_ENV_VAR') ? service('some_service') : service('some_other_service')"));};

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.

@carsonbotcarsonbot added this to the6.1 milestoneFeb 16, 2022
@carsonbotcarsonbot changed the titleAllow using expressions as service factories[DependencyInjection] Allow using expressions as service factoriesFeb 16, 2022
Copy link
Member

@nicolas-grekasnicolas-grekas left a 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
Copy link
ContributorAuthor

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 thegetConstructor method, would it be fine to just returnnull in case of a factory expression since as far as I can see it is used to get the constructor arguments which doesn't apply in the case of an expression?

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.

@jvasseurjvasseurforce-pushed theexpr-factory branch 2 times, most recently from61aa6c9 to65ff961CompareFebruary 18, 2022 13:40
@jvasseur
Copy link
ContributorAuthor

I've decided to go with returning theReflectionFunction of an empty closure inAbstractRecursivePass::getConstructor since an expression can be seen as an anonymous function without any argument.

@nicolas-grekas
Copy link
Member

nicolas-grekas commentedFeb 21, 2022
edited
Loading

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
Copy link
ContributorAuthor

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
Copy link
Member

nicolas-grekas commentedFeb 22, 2022
edited
Loading

It took me a while to figure out an approach that could work, and here it is:#45512
Please have a look!

@nicolas-grekas
Copy link
Member

nicolas-grekas commentedMar 4, 2022
edited
Loading

Closing in favor of#45512

fabpot added a commit that referenced this pull requestMar 26, 2022
…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
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@nicolas-grekasnicolas-grekasnicolas-grekas left review comments

Assignees

No one assigned

Projects

None yet

Milestone

6.1

Development

Successfully merging this pull request may close these issues.

3 participants

@jvasseur@nicolas-grekas@carsonbot

[8]ページ先頭

©2009-2025 Movatter.jp