File: attributes.md

package info (click to toggle)
php-di 7.1.1-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 2,932 kB
  • sloc: php: 10,572; makefile: 42; xml: 17; sh: 10; pascal: 5
file content (139 lines) | stat: -rw-r--r-- 3,631 bytes parent folder | download | duplicates (2)
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).