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] Add Parameter attribute to bind container parameters to services.#44780

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
maldoinc wants to merge1 commit intosymfony:6.1frommaldoinc:feat/parameter-attribute
Closed

Conversation

@maldoinc
Copy link
Contributor

QA
Branch?6.1
Bug fix?no
New feature?yes
Deprecations?no
Tickets
LicenseMIT
Doc PRnot yet created. Will update if PR looks to be merged

Hi all.

This PR proposes the addition of a new Attribute to bind container parameters to services.

Motivation:
Seeing as Symfony has been adopting the usage of attributes to configure services, this would add the possibility to bind parameters and have services be self-contained instead of having their configuration split into multiple files.

In the application we develop most services which require parameters have their values declared in a Yaml file via the following syntax.

Acme\Service\DummyService:    arguments:        $isDebugEnv: "%kernel.debug%"

Downsides

  • Configuration remains in a separate file which also grows in size with the number of services.
  • Duplication of class,namespace and arguments
  • Error-prone refactoring: namespace, class name, arguments in the yaml file are not updated by any IDE or plugin when they change.

Recently I also became aware of the#[Autoconfigure(bind:['$isDebugEnv' => '%kernel.debug%'])] syntax. This addresses the separation of the declaration into multiple files and follows the class when moved around. If this PR won't pass then this would be our preferred method once the application I help develop is upgraded to PHP 8.

  • The argument name is passed as a string tobind and is also not refactored and is also duplicated.
  • Can only be applied to a class rather than the constructor, having argument names and the constructor be visually "far" from each-other.

Proposal:

TheParameter (orBindParameter, name tbd) attribute which is applied to parameters and properties (to account for promoted properties) and has the parameter name bound via a compiler pass. Currently only parameters are supported so the following is not a valid syntax#[Parameter("%kernel.logs_dir%/subdir")] (also tbd).

This would address the concerns from both previous approaches and in my opinion has a main advantage: It does not rely on strings for the argument name. The php community has been moving away for quite some time now from hard-coded strings to reference things. Classes now have the::class syntax, and references to functions, properties and methods went from strings and arrays to having first-class support with the new(...) syntax.

The downside of this new attribute would be that it is yet another way to do something that is already possible. On the other hand, Symfony has always had multiple options to do configuration (annotations and now attributes, yaml, xml, php).

Example:

class DummyService{publicfunction__construct(#[Parameter("kernel.debug")]publicbool$isDebugEnv)    {    }}

Looking forward to your thoughts. Related issue:#40327

HypeMC, kbond, and bresam reacted with thumbs up emojimichaljusiega reacted with hooray emojiderrabus reacted with eyes emoji
@carsonbotcarsonbot added this to the6.1 milestoneDec 23, 2021
@carsonbotcarsonbot changed the titleAdd Parameter attribute to bind container parameters to services.[DependencyInjection] Add Parameter attribute to bind container parameters to services.Dec 23, 2021
@carsonbot
Copy link

Hey!

I think@fractalzombie has recently worked with this code. Maybe they can help review this?

Cheers!

Carsonbot

@kbond
Copy link
Member

kbond commentedJan 13, 2022
edited
Loading

I like this idea but what about binding services as well? I'm thinking just a singleBind attribute:

class DummyService{publicfunction__construct(        #[Bind('@another.service.id')]publicAnotherService$service,        #[Bind('%kernel.debug%')]publicbool$isDebugEnv    ) {    }}

This would be a shortcut to the following (which is possible now):

#[Autoconfigure(bind: ['$service' =>'@another.service.id','$isDebugEnv' =>'%kernel.debug%',])]class DummyService{publicfunction__construct(publicAnotherService$service,publicbool$isDebugEnv)    {    }}

@stof
Copy link
Member

I like this idea but what about binding services as well?

Isn't it already solved in some way with theTarget attribute (which relies on named autowiring aliases rather than on service ids) ?

@kbond
Copy link
Member

kbond commentedJan 13, 2022
edited
Loading

Isn't it already solved in some way with the Target attribute (which relies on named autowiring aliases rather than on service ids) ?

Partially, but not for service ids themselves and this was what I was looking for. I'm envisioning this purely as a short-hand forAutoconfigure(bind).

@maldoinc
Copy link
ContributorAuthor

maldoinc commentedJan 15, 2022
edited
Loading

The reason I did not consider it for services is that services are already automatically injected on top of already having theRequired attribute docblock annotation and the{with,set}Something methods as well. For services which have ids rather than the FCCN I figured one of the existing solutions could be used instead.

The other thing is that this accepts only parameters rather than a string with a parameter in it such as%param%/some_string. For this, I figured since this is right next to the constructor, the concatenation could be done there. The other reason being that#[Parameter('kernel.debug') looks "cleaner" than#[Parameter("%kernel.debug%")], but something like#[Bind("%kernel.debug%"]) also has its merits. Both syntaxes are fine by me so we can go with whichever is more suitable to the project.

@kbond
Copy link
Member

kbond commentedJan 20, 2022
edited
Loading

The reason I did not consider it for services is that services are already automatically injected on top of already having the Required attribute docblock annotation and the {with,set}Something methods as well. For services which have ids rather than the FCCN I figured one of the existing solutions could be used instead.

Yes, this would just be a shortcut forAutoconfigure(bind: ...). There is no other way to configure service id's (that I'm aware).

Recently I also became aware of the #[Autoconfigure(bind:['$isDebugEnv' => '%kernel.debug%'])] syntax. This addresses the separation of the declaration into multiple files and follows the class when moved around. If this PR won't pass then this would be our preferred method once the application I help develop is upgraded to PHP 8.

  • The argument name is passed as a string to bind and is also not refactored and is also duplicated.
  • Can only be applied to a class rather than the constructor, having argument names and the constructor be visually "far" from each-other.

To me, this argument applies to binding services as well as parameters.

parameters rather than a string with a parameter in it such as %param%/some_string

SinceAutoconfigure(bind: ...) supports this, I believe the parameter attribute should as well.

@stof
Copy link
Member

Based on the various comments here, I think there is a misunderstand about whatAutoconfigure(bind: ...) is doing.

theAutoconfigure attribute is not about replacing file-level default bindings. It is about registering a type into the autoconfiguration system (seeContainerBundler::registerForAutoconfiguration) so that all services being of that type will be autoconfigured with that rule (if they have opted-in for autoconfiguration)

@kbond
Copy link
Member

kbond commentedJan 20, 2022
edited
Loading

So to clarify, for my second code blockhere. This would register the$service binding globally (not just in this file)?

Looking at#39804.

This should typically be added on a base class/interface to tell how implementations of such a base type should be autoconfigured.

Indeed, this was a misunderstanding on my part.

So what I'm looking for and I believe@maldoinc is looking for (for parameters at least) is a way to take this config:

services:App\SomeService:        -'@some.other.service'        -'%some.parameter%'

And use constructor parameter attributes to configure:

class SomeService{publicfunction __construct(        #[???('some.other.service')]        public AnotherService $service,        #[???('some.parameter')]public string$parameter    ) {    }}

@stof
Copy link
Member

@kbond the Autoconfigure attribute would register a binding applied on all (autoconfigured) service whose class is a DummyService or a child class of DummyService

kbond reacted with thumbs up emoji

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.

I would prefer requiring the% around the parameter name, as this gives more flexibility, eg:
#[Parameter('%kernel.project_dir%/var/foo')]

class AutowirePassTestextends TestCase
{
/**
* @requires PHP 8.0

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

not needed anymore


class AutowiredParameterTest
{
publicfunction__construct(#[Parameter("parameter.test")]publicstring$testParam)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

please use single-quoted strings

@nicolas-grekas
Copy link
Member

Thank you@maldoinc for this PR. I'm closing it because we figured out another attribute would be more generic. See#45657, you might like it.

fabpot added a commit that referenced this pull requestMar 18, 2022
…te (kbond)This PR was merged into the 6.1 branch.Discussion----------[DependencyInjection] add `Autowire` parameter attribute| Q             | A| ------------- | ---| Branch?       | 6.1| Bug fix?      | no| New feature?  | yes| Deprecations? | no| Tickets       | n/a| License       | MIT| Doc PR        | todoReplaces#45573 &#44780 with a single new `Autowire` attribute:```phpclass MyService{    public function __construct(        #[Autowire(service: 'some_service')]        private $service1,        #[Autowire(expression: 'service("App\\Mail\\MailerConfiguration").getMailerMethod()')        private $service2,        #[Autowire(value: '%env(json:file:resolve:AUTH_FILE)%')]        private $parameter1,        #[Autowire(value: '%kernel.project_dir%/config/dir')]        private $parameter2,    ) {}}```Works with controller arguments as well:```phpclass MyController{    public function someAction(        #[Autowire(service: 'some_service')]        $service1,        #[Autowire(expression: 'service("App\\Mail\\MailerConfiguration").getMailerMethod()')        $service2,        #[Autowire(value: '%env(json:file:resolve:AUTH_FILE)%')]        $parameter1,        #[Autowire(value: '%kernel.project_dir%/config/dir')]        $parameter2,    ): Response {}}```Commits-------d43fe42 [DependencyInjection] add `Autowire` parameter attribute
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@kbondkbondkbond left review comments

@nicolas-grekasnicolas-grekasnicolas-grekas left review comments

@stofstofstof left review comments

@dunglasdunglasAwaiting requested review from dunglasdunglas is a code owner

Assignees

No one assigned

Projects

None yet

Milestone

6.1

Development

Successfully merging this pull request may close these issues.

6 participants

@maldoinc@carsonbot@kbond@stof@nicolas-grekas@derrabus

[8]ページ先頭

©2009-2025 Movatter.jp