@@ -86,13 +86,27 @@ autowired:
86
86
87
87
The autowiring subsystem will detect the dependencies of the ``TwitterClient ``
88
88
class by parsing its constructor. For instance it will find here an instance of
89
- a ``Rot13Transformer `` as dependency. If an existing service definition (and only
90
- one – see below) is of the required type, this service will be injected. If it's
91
- not the case (like in this example), the subsystem is smart enough to automatically
92
- register a private service for the ``Rot13Transformer `` class and set it as first
93
- argument of the ``twitter_client `` service. Again, it can work only if there is one
94
- class of the given type. If there are several classes of the same type, you must
95
- use an explicit service definition or register a default implementation.
89
+ a ``Rot13Transformer `` as dependency.
90
+
91
+ The subsystem will first try to find a service whose id is the required type, so
92
+ here it'll search for a service named ``AppBundle\Rot13Transformer ``.
93
+ It will be considered as the default implementation and will win over any other
94
+ services implementing the required type.
95
+
96
+ *In case this service does not exist *, the subsystem will detect the types of
97
+ all services and check if one - and only one - implements the required type, and
98
+ inject it if it's the case. If there are several services of the same type, an
99
+ exception will be thrown. You'll have to use an explicit service definition or
100
+ register a default implementation by creating a service or an alias whose id is
101
+ the required type (as seen above).
102
+ Note that this step is deprecated and will no longer be done in 4.0. The
103
+ subsystem will directly pass to the third check.
104
+
105
+ At last, if no service implements the required type, as it's the case here, the
106
+ subsystem is, as long as it's a concrete class, smart enough to automatically
107
+ register a private service for it.
108
+ Here it'll register a private service for the ``Rot13Transformer `` class and set
109
+ it as first argument of the ``twitter_client `` service.
96
110
97
111
As you can see, the autowiring feature drastically reduces the amount of configuration
98
112
required to define a service. No more arguments section! It also makes it easy
@@ -185,7 +199,9 @@ And update ``TwitterClient`` to depend of this new interface::
185
199
}
186
200
187
201
Finally the service definition must be updated because, obviously, the autowiring
188
- subsystem isn't able to find itself the interface implementation to register:
202
+ subsystem isn't able to find itself the interface implementation to register.
203
+ You have to indicate which service must be injected for your interface when
204
+ using autowiring:
189
205
190
206
.. configuration-block ::
191
207
@@ -194,6 +210,10 @@ subsystem isn't able to find itself the interface implementation to register:
194
210
services :
195
211
AppBundle\Rot13Transformer : ~
196
212
213
+ # the ``AppBundle\Rot13Transformer`` service will be injected when
214
+ # a ``AppBundle\TransformerInterface`` type-hint is detected
215
+ AppBundle\TransformerInterface : ' @AppBundle\Rot13Transformer'
216
+
197
217
AppBundle\TwitterClient :
198
218
autowire : true
199
219
@@ -207,32 +227,43 @@ subsystem isn't able to find itself the interface implementation to register:
207
227
<services >
208
228
<service id =" AppBundle\Rot13Transformer" />
209
229
230
+ <service id =" AppBundle\TransformerInterface" alias =" AppBundle\Rot13Transformer" />
231
+
210
232
<service id =" AppBundle\TwitterClient" autowire =" true" />
211
233
</services >
212
234
</container >
213
235
214
236
.. code-block :: php
215
237
216
238
use AppBundle\Rot13Transformer;
239
+ use AppBundle\TransformerInterface;
217
240
use AppBundle\TwitterClient;
218
241
219
242
// ...
220
243
$container->register(Rot13Transformer::class);
244
+ $container->setAlias(TransformerInterface::class, Rot13Transformer::class);
245
+
221
246
$container->autowire(TwitterClient::class);
222
247
223
- The autowiring subsystem detects that the ``AppBundle\Rot13Transformer `` service
224
- implements the ``TransformerInterface `` and injects it automatically. Even when
225
- using interfaces (and you should), building the service graph and refactoring
226
- the project is easier than with standard definitions.
248
+ Thanks to the ``AppBundle\TransformerInterface `` alias, the autowiring subsystem
249
+ knows that the ``AppBundle\Rot13Transformer `` service must be injected when
250
+ dealing with the ``TransformerInterface `` and injects it automatically. Even
251
+ when using interfaces (and you should), building the service graph and
252
+ refactoring the project is easier than with standard definitions.
227
253
228
254
.. _service-autowiring-alias :
229
255
230
256
Dealing with Multiple Implementations of the Same Type
231
257
------------------------------------------------------
232
258
233
- Last but not least, the autowiring feature allows to specify the default implementation
234
- of a given type. Let's introduce a new implementation of the ``TransformerInterface ``
235
- returning the result of the ROT13 transformation uppercased::
259
+ To deal with multiple implementations of the same type, the manipulation is the
260
+ same as when dealing with an interface. You have to register a service whose id
261
+ is your type: this will indicate to the autowiring subsystem which service to
262
+ use by default for this type.
263
+ So if you have several services implementing the same type, you can decide which
264
+ one the subsystem should use. Let's introduce a new implementation of the
265
+ ``TransformerInterface `` returning the result of the ROT13 transformation
266
+ uppercased::
236
267
237
268
namespace AppBundle;
238
269
@@ -274,6 +305,9 @@ transformer::
274
305
*/
275
306
public function tweetAction(Request $request, TwitterClient $twitterClient)
276
307
{
308
+ // Here the client is automatically injected because it's the default
309
+ // implementation
310
+
277
311
return $this->tweet($request, $twitterClient);
278
312
}
279
313
@@ -315,6 +349,9 @@ and a Twitter client using it:
315
349
services :
316
350
AppBundle\Rot13Transformer : ~
317
351
352
+ # the ``AppBundle\Rot13Transformer`` service will *always* be used
353
+ # when ``AppBundle\TransformerInterface`` is detected by the
354
+ # autowiring subsystem
318
355
AppBundle\TransformerInterface : ' @AppBundle\Rot13Transformer'
319
356
320
357
AppBundle\TwitterClient :
@@ -359,16 +396,16 @@ and a Twitter client using it:
359
396
360
397
// ...
361
398
$container->register(Rot13Transformer::class);
362
- $container->setAlias(TransformerInterface::class, Rot13Transformer::class)
399
+ $container->setAlias(TransformerInterface::class, Rot13Transformer::class);
363
400
364
401
$container->autowire(TwitterClient::class);
365
402
$container->autowire(UppercaseTransformer::class);
366
403
$container->register('uppercase_twitter_client', TwitterClient::class)
367
404
->addArgument(new Reference(UppercaseTransformer::class));
368
405
369
406
This deserves some explanations. You now have two services implementing the
370
- ``TransformerInterface ``. The autowiring subsystem cannot guess which one
371
- to use which leads to errors like this:
407
+ ``TransformerInterface ``. As said earlier, the autowiring subsystem cannot guess
408
+ which one to use which leads to errors like this:
372
409
373
410
.. code-block :: text
374
411
0 commit comments