8000 [DependencyInjection] add `Autowire` parameter attribute by kbond · Pull Request #45657 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[DependencyInjection] add Autowire parameter attribute #45657

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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 18, 2022

Conversation

kbond
Copy link
Member
@kbond kbond commented Mar 6, 2022
Q A
Branch? 6.1
Bug fix? no
New feature? yes
Deprecations? no
Tickets n/a
License MIT
Doc PR todo

Replaces #45573 & #44780 with a single new Autowire attribute:

class 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:

class 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 {}
}

Copy link
Member
@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

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

What about calling Yaml::parse() before calling YamlFileLoader::resolveServices()?

@nicolas-grekas
Copy link
Member
nicolas-grekas commented Mar 7, 2022

What about calling Yaml::parse() before calling YamlFileLoader::resolveServices()?

I'm withdrawing this comment, bad idea :)

Another idea, using named arguments:

  • #[Autowire(service: MailerConfiguration::class)
  • #[Autowire(expr: 'service("App\Mail\MailerConfiguration").getMailerMethod()')
  • #[Autowire(value: '%kernel.project_dir%'/var/foo')

I think that's my preference: no custom yaml-like strings and more explicit than standalone attributes.

@kbond kbond force-pushed the autowire-attribute branch from fc249f1 to 2fa653b Compare March 7, 2022 12:57
@kbond
Copy link
Member Author
kbond commented Mar 7, 2022

I've made this change and also added the raw parameter argument (updated PR description).

What about controller action arguments? Separate PR?

Copy link
Member
@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

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

What about controller action arguments? Separate PR?

same PR to me, it's the same topic

@kbond kbond force-pushed the autowire-attribute branch from 2fa653b to c58e6ea Compare March 7, 2022 15:33
Copy link
Member
@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

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

Here are some minor comments. I like it. How about you? Let's close the two previous ones?

@kbond kbond force-pushed the autowire-attribute branch 2 times, most recently from 735a6ee to d3a1794 Compare March 7, 2022 16:34
@kbond
Copy link
Member Author
kbond commented Mar 7, 2022

Here are some minor comments. I like it. How about you? Let's close the two previous ones?

Made these changes. I am happy with it as well - let's close them!

Few questions:

  1. Should I change the service Reference behaviour for nullable parameters?
  2. For controller arguments: are only service's allowed? No expressions/parameters?

@nicolas-grekas
Copy link
Member

Should I change the service Reference behaviour for nullable parameters?

That'd make sense yes

For controller arguments: are only service's allowed? No expressions/parameters?

expressions/parameters should be allowed. There is a hack using 'current' as factory right now, you'll see it in the pass.

@kbond kbond force-pushed the autowire-attribute branch from d3a1794 to d360af6 Compare March 7, 2022 17:29
@kbond kbond force-pushed the autowire-attribute branch 2 times, most recently from 45d49dc to ac210cf Compare March 7, 2022 18:12
@kbond
Copy link
Member Author
kbond commented Mar 7, 2022

Ok, I have the controller argument support working but implementation might need some work.

@kbond kbond force-pushed the autowire-attribute branch from ac210cf to 000de70 Compare March 7, 2022 18:24
@kbond kbond force-pushed the autowire-attribute branch 2 times, most recently from 63094c4 to d9b0417 Compare March 8, 2022 19:01
nicolas-grekas
Copy link
Member
@nicolas-grekas nicolas-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 like it, thanks!
(I pushed some tweaks)

@fabpot
Copy link
Member
fabpot commented Mar 18, 2022

Thank you @kbond.

@fabpot fabpot merged commit 7248e16 into symfony:6.1 Mar 18, 2022
@kbond kbond deleted the autowire-attribute branch March 18, 2022 13:54
fabpot added a commit that referenced this pull request Mar 22, 2022
…ementation (kbond)

This PR was merged into the 6.1 branch.

Discussion
----------

[DependencyInjection] adjust `Autowire` attribute implementation

| Q             | A
| ------------- | ---
| Branch?       | 6.1
| Bug fix?      | no
| New feature?  | yes
| Deprecations? | no
| Tickets       | #45657 (comment)
| License       | MIT
| Doc PR        | todo

Per discussion with @nicolas-grekas, we've decided to improve the DX of the attribute a bit. The implementation from #45657 still works as described there. This allows for the first `Autowire` constructor argument to be used for services/expressions by adding a _familiar_ prefix (`@` for services, `@=` for expressions):

```php
class MyService
{
    public function __construct(
        #[Autowire('@some_service')]
        private $service1,

        #[Autowire('@=service("App\\Mail\\MailerConfiguration").getMailerMethod()')
        private $service2,

        #[Autowire('%env(json:file:resolve:AUTH_FILE)%')]
        private $parameter1,
    ) {}
}
```

Commits
-------

c86aa7a [DependencyInjection] adjust `Autowire` attribute implementation
@fabpot fabpot mentioned this pull request Apr 15, 2022
wouterj added a commit to symfony/symfony-docs that referenced this pull request May 1, 2022
…attribute (kbond)

This PR was merged into the 6.1 branch.

Discussion
----------

[DependencyInjection][HttpKernel] document `Autowire` attribute

Symfony PRs: symfony/symfony#45657 & symfony/symfony#45783
Closes #16625.
Closes #16636

Commits
-------

bf8be7e Move the autowire attribute sections
f32aec1 [DI][HttpKernel] document `Autowire` attribute
*
* @author Kevin Bond <kevinbond@gmail.com>
*/
#[\Attribute(\Attribute::TARGET_PARAMETER)]
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you think this #[\Attribute(\Attribute::TARGET_PARAMETER, \Attribute::TARGET_PROPERTY)] can be used here? When using Attribute with promoted property constructor.

Copy link
Member Author
@kbond kbond May 31, 2022

Choose a reason for hiding this comment

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

#[\Attribute(\Attribute::TARGET_PARAMETER] can be used on promoted properties. See https://github.com/symfony/symfony/pull/45657/files#diff-a4f7e7528218aa6d151b1e68834393c6ae958540ec31ffa49ce3207998e77dd2R33

Copy link
Member

Choose a reason for hiding this comment

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

why would we? TARGET_PARAMETER is enough to target a promoted argument

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes you're right TARGET_PARAMETER is enough here. Thank you for your quick response :)

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm facing the same problem.

TARGET_PARAMETER is working as well with properties for constructor, however not working especially with reflection mechanism on reflection property.

See https://3v4l.org/gDeYA what I mean.

Also PHPStorm suggests not to use this attribute on property promoted:
obraz

cc @kbond @nicolas-grekas @qdequippe

Copy link
Member Author

Choose a reason for hiding this comment

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

Could this be a bug in PHP or a missing detail in the implementation? The opposite is a problem too: https://3v4l.org/tBjj2. Somewhat related PHPStan issue: phpstan/phpstan#4418.

Copy link
Contributor

Choose a reason for hiding this comment

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

As far as I understand, PHPStan literally "silence" this situation, right?

For me isn't looks like a PHP bug, in my opinion we should add TARGET_PROPERTY flag. ;)

Copy link
Member
@nicolas-grekas nicolas-grekas Jun 20, 2022

Choose a reason for hiding this comment

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

To me it's a limitation of the engine and the engine should be improved: from a descriptive pov, both variants give all the possible hints to make things clear. The engine is not clever enough yet.
The alternative is to not use CPP but it would be a shame to accept this state of things :) Patching the attribute would be wrong: Autowire should NOT be allowed on properties.
Could you please open a bug report about this on php-src?

Copy link
Member
@derrabus derrabus Jun 21, 2022

Choose a reason for hiding this comment

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

See https://3v4l.org/gDeYA what I mean.

Calling newInstance() for arbitrary attributes is a footgun. Attributes could point to undefined classes and the attribute constructor could have side effects. The reflection API by design provides you with enough information to decide whether you need an actual instance of an attribute. Only call newInstance() on attributes you know and that your code actually needs to work with.

I agree with @nicolas-grekas that there's nothing we should do on our side.

Copy link
Member Author

Choose a reason for hiding this comment

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

I agree as well. At least until a time where the attribute can actually be used with property injection.

GromNaN added a commit to GromNaN/symfony that referenced this pull request Mar 28, 2025
Introduced in symfony#45657

symfony/dependency-injection 6.4+ is required, so the class always exists
GromNaN added a commit to GromNaN/symfony that referenced this pull request Mar 28, 2025
Introduced in symfony#45657

symfony/dependency-injection 6.4+ is required, so the class always exists
GromNaN added a commit that referenced this pull request Mar 28, 2025
…f DI `Autowire` class (GromNaN)

This PR was merged into the 7.3 branch.

Discussion
----------

[HttpKernel] Remove always-true condition on existence of DI `Autowire` class

| Q             | A
| ------------- | ---
| Branch?       | 7.3
| Bug fix?      | no
| New feature?  | no
| Deprecations? | no
| Issues        | -
| License       | MIT

This condition was introduced in #45657

The class `RegisterControllerArgumentLocatorsPass` requires the DI component, which cannot be < 6.4 due to a [conflict rule in composer.json](https://github.com/symfony/symfony/blob/79ea49c772ce4b39f414cde5648ad347c3bbcfd7/src/Symfony/Component/HttpKernel/composer.json#L33). So the `Autoconfigure` class always exists.

Commits
-------

3975043 Remove always-true condition
symfony-splitter pushed a commit to symfony/http-kernel that referenced this pull request Mar 28, 2025
Introduced in symfony/symfony#45657

symfony/dependency-injection 6.4+ is required, so the class always exists
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants
0