@@ -105,6 +105,112 @@ working with optional dependencies. It is also more difficult to use in
105
105
combination with class hierarchies: if a class uses constructor injection
106
106
then extending it and overriding the constructor becomes problematic.
107
107
108
+ Immutable-setter Injection
109
+ --------------------------
110
+
111
+ .. versionadded :: 4.3
112
+
113
+ The ``immutable-setter `` injection was introduced in Symfony 4.3.
114
+
115
+ Another possible injection is to use a method which returns a separate instance
116
+ by cloning the original service, this approach allows you to make a service immutable::
117
+
118
+ // ...
119
+ use Symfony\Component\Mailer\MailerInterface;
120
+
121
+ class NewsletterManager
122
+ {
123
+ private $mailer;
124
+
125
+ /**
126
+ * @required
127
+ * @return static
128
+ */
129
+ public function withMailer(MailerInterface $mailer)
130
+ {
131
+ $new = clone $this;
132
+ $new->mailer = $mailer;
133
+
134
+ return $new;
135
+ }
136
+
137
+ // ...
138
+ }
139
+
140
+ In order to use this type of injection, don't forget to configure it:
141
+
142
+ .. configuration-block ::
143
+
144
+ .. code-block :: yaml
145
+
146
+ # config/services.yaml
147
+ services :
148
+ # ...
149
+
150
+ app.newsletter_manager :
151
+ class : App\Mail\NewsletterManager
152
+ calls :
153
+ - [withMailer, ['@mailer'], true]
154
+
155
+ .. code-block :: xml
156
+
157
+ <!-- config/services.xml -->
158
+ <?xml version =" 1.0" encoding =" UTF-8" ?>
159
+ <container xmlns =" http://symfony.com/schema/dic/services"
160
+ xmlns : xsi =" https://www.w3.org/2001/XMLSchema-instance"
161
+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
162
+ https://symfony.com/schema/dic/services/services-1.0.xsd" >
163
+
164
+ <services >
165
+ <!-- ... -->
166
+
167
+ <service id =" app.newsletter_manager" class =" App\Mail\NewsletterManager" >
168
+ <call method =" withMailer" returns-clone =" true" >
169
+ <argument type =" service" id =" mailer" />
170
+ </call >
171
+ </service >
172
+ </services >
173
+ </container >
174
+
175
+ .. code-block :: php
176
+
177
+ // config/services.php
178
+ use App\Mail\NewsletterManager;
179
+ use Symfony\Component\DependencyInjection\Reference;
180
+
181
+ // ...
182
+ $container->register('app.newsletter_manager', NewsletterManager::class)
183
+ ->addMethodCall('withMailer', [new Reference('mailer')], true);
184
+
185
+ .. note ::
186
+
187
+ If you decide to use autowiring, this type of injection requires
188
+ that you add a ``@return static `` docblock in order for the container
189
+ to be capable of registering the method.
190
+
191
+ This approach is useful if you need to configure your service according to your needs,
192
+ so, here's the advantages of immutable-setters:
193
+
194
+ * Immutable setters works with optional dependencies, this way, if you don't need
195
+ a dependency, the setter don't need to be called.
196
+
197
+ * Like the constructor injection, using immutable setters force the dependency to stay
198
+ the same during the lifetime of a service.
199
+
200
+ * This type of injection works well with traits as the service can be composed,
201
+ this way, adapting the service to your application requirements is easier.
202
+
203
+ * The setter can be called multiple times, this way, adding a dependency to a collection
204
+ becomes easier and allows you to add a variable number of dependencies.
205
+
206
+ The disadvantages are:
207
+
208
+ * As the setter call is optional, a dependency can be null during execution,
209
+ you must check that the dependency is available before calling it.
210
+
211
+ * Unless the service is declared lazy, it is incompatible with services
212
+ that reference each other in what are called circular loops.
213
+
108
214
Setter Injection
109
215
----------------
110
216
@@ -180,6 +286,9 @@ This time the advantages are:
180
286
the method adds the dependency to a collection. You can then have a variable
181
287
number of dependencies.
182
288
289
+ * Like the immutable-setter one, this type of injection works well with
290
+ traits and allows you to compose your service.
291
+
183
292
The disadvantages of setter injection are:
184
293
185
294
* The setter can be called more than just at the time of construction so
0 commit comments