You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feature #42039 [DependencyInjection] Autoconfigurable attributes on methods, properties and parameters (ruudk)
This PR was merged into the 5.4 branch.
Discussion
----------
[DependencyInjection] Autoconfigurable attributes on methods, properties and parameters
| Q | A
| ------------- | ---
| Branch? | 5.4
| Bug fix? |no
| New feature? | yes
| Deprecations? |no
| Tickets |
| License | MIT
| Doc PR |
## Introduction
symfony/symfony#39897 introduced the possibility auto configure classes that were annotated with attributes:
```php
$container->registerAttributeForAutoconfiguration(
MyAttribute::class,
static function (ChildDefinition $definition, MyAttribute $attribute, \ReflectionClass $reflector): void {
$definition->addTag('my_tag', ['some_property' => $attribute->someProperty]);
}
);
```
This works great. But it only works when the attribute is added on the class.
With this PR, it's now possible to also auto configure methods, properties and parameters.
## How does it work?
Let's say you have an attribute that targets classes and methods like this:
```php
#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::TARGET_PROPERTY)]
final class MyAttribute
{
}
```
You have two services that use them:
```php
#[MyAttribute]
class MyService {
}
class MyOtherService {
#[MyAttribute]
public function myMethod() {}
}
```
You can now use `registerAttributeForAutoconfiguration` in your extension, together with a union of the types that you want to seach for. In this example, the extension only cares for classes and methods, so it uses `\ReflectionClass|\ReflectionMethod $reflector`:
```php
final class MyBundleExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container) : void
{
$container->registerAttributeForAutoconfiguration(
MyAttribute::class,
static function (ChildDefinition $definition, MyAttribute $attribute, \ReflectionClass|\ReflectionMethod $reflector) : void {
$args = [];
if ($reflector instanceof \ReflectionMethod) {
$args['method'] = $reflector->getName();
}
$definition->addTag('my.tag', $args);
}
);
}
}
```
This will tag `MyService` with `my.tag` and it will tag `MyOtherService` with `my.tag, method: myMethod`
If the extension also wants to target the properties that are annotated with attributes, it can either change the union to `\ReflectionClass|\ReflectionMethod|\ReflectionProperty $reflector` or it can just use `\Reflector $reflector` and do the switching in the callable.
## Another example
Let's say you have an attribute like this:
```php
#[Attribute(Attribute::TARGET_CLASS)]
final class MyAttribute
{
}
```
and you use it like this:
```php
$container->registerAttributeForAutoconfiguration(
MyAttribute::class,
static function (ChildDefinition $definition, MyAttribute $attribute, \ReflectionClass|\ReflectionMethod $reflector) : void {
$definition->addTag('my.tag');
}
);
```
you'll get an error saying that `ReflectionMethod` is not possible as the attribute only targets classes.
Commits
-------
917fcc09f7 [DependencyInjection] Autoconfigurable attributes on methods, properties and parameters
0 commit comments