1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
---
layout: documentation
current_menu: attributes
---
# Attributes
On top of [autowiring](autowiring.md) and [PHP configuration files](php-definitions.md), you can define injections using PHP 8 attributes.
Using attributes do not affect performances when [compiling the container](performances.md). For a non-compiled container, the PHP reflection is used but the overhead is minimal.
## Setup
Enable attributes [via the `ContainerBuilder`](container-configuration.md):
```php
$containerBuilder->useAttributes(true);
```
## Inject
`#[Inject]` lets you define where PHP-DI should inject something, and optionally what it should inject.
It can be used on:
- the constructor (constructor injection)
- methods (setter/method injection)
- properties (property injection)
*Note: property injections occur after the constructor is executed, so any injectable property will be null inside `__construct`.*
**Note: `#[Inject]` ignores types declared in phpdoc. Only types specified in PHP code are considered.**
Here is an example of all possible uses of the `#[Inject]` attribute:
```php
use DI\Attribute\Inject;
class Example
{
/**
* Attribute combined with a type on the property:
*/
#[Inject]
private Foo $property1;
/**
* Explicit definition of the entry to inject:
*/
#[Inject('db.host')]
private $property2;
/**
* Alternative to the above:
*/
#[Inject(name: 'db.host')]
private $property3;
/**
* The constructor is of course always called, but the
* #[Inject] attribute can be used on a parameter
* to specify what to inject.
*/
public function __construct(Foo $foo, #[Inject('db.host')] $dbHost)
{
}
/**
* #[Inject] tells PHP-DI to call the method.
* By default, PHP-DI uses the PHP types to find the service to inject:
*/
#[Inject]
public function method1(Foo $param)
{
}
/**
* #[Inject] can be used at the parameter level to
* specify what to inject.
* Note: #[Inject] *must be place* on the function too.
*/
#[Inject]
public function method2(#[Inject('db.host')] $param)
{
}
/**
* Explicit definition of the entries to inject:
*/
#[Inject(['db.host', 'db.name'])]
public function method3($param1, $param2)
{
}
/**
* Explicit definition of parameters by their name
* (types are used for the other parameters):
*/
#[Inject(['param2' => 'db.host'])]
public function method4(Foo $param1, $param2)
{
}
}
```
*Note: remember to import the attribute class via `use DI\Attribute\Inject;`.*
### Troubleshooting attributes
- remember to import the attribute class via `use DI\Attribute\Inject;`
- `#[Inject]` is not meant to be used on the method to call with [`Container::call()`](container.md#call) (it will be ignored)
- `#[Inject]` ignores types declared in phpdoc. Only types specified in PHP code are considered.
Note that `#[Inject]` is implicit on all constructors (because constructors must be called to create an object).
## Injectable
The `#[Injectable]` attribute lets you set options on injectable classes:
```php
use DI\Attribute\Injectable;
#[Injectable(lazy: true)]
class Example
{
}
```
**The `#[Injectable]` attribute is optional: by default, all classes are injectable.**
## Limitations
There are things that can't be defined with attributes:
- values (instead of classes)
- mapping interfaces to implementations
- defining entries with an anonymous function
For that, you can combine attributes with [definitions in PHP](php-definitions.md).
|