Skip to content

Commit 3b75147

Browse files
committed
update
1 parent 1f6edd4 commit 3b75147

File tree

2 files changed

+58
-30
lines changed

2 files changed

+58
-30
lines changed

best_practices/security.rst

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -328,18 +328,9 @@ the same ``getAuthorEmail()`` logic you used above:
328328
}
329329
}
330330
331-
To enable the security voter in the application, define a new service:
332-
333-
.. code-block:: yaml
334-
335-
# app/config/services.yml
336-
services:
337-
# ...
338-
app.post_voter:
339-
class: AppBundle\Security\PostVoter
340-
arguments: ['@security.access.decision_manager']
341-
public: false
342-
tags: [security.voter]
331+
Your application will :ref:`autoconfigure <services-autoconfigure>` your security
332+
voter and inject a ``AccessDecisionManagerInterface`` instance in it thanks to
333+
:doc:`autowiring </service_container/autowiring>`.
343334

344335
Now, you can use the voter with the ``@Security`` annotation:
345336

service_container/autowiring.rst

Lines changed: 55 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,27 @@ autowired:
8686

8787
The autowiring subsystem will detect the dependencies of the ``TwitterClient``
8888
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.
96110

97111
As you can see, the autowiring feature drastically reduces the amount of configuration
98112
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::
185199
}
186200

187201
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:
189205

190206
.. configuration-block::
191207

@@ -194,6 +210,10 @@ subsystem isn't able to find itself the interface implementation to register:
194210
services:
195211
AppBundle\Rot13Transformer: ~
196212
213+
# the ``AppBundle\Rot13Transformer`` service will be injected when
214+
# a ``AppBundle\TransformerInterface`` type-hint is detected
215+
AppBundle\TransformerInterface: '@AppBundle\Rot13Transformer'
216+
197217
AppBundle\TwitterClient:
198218
autowire: true
199219
@@ -207,32 +227,43 @@ subsystem isn't able to find itself the interface implementation to register:
207227
<services>
208228
<service id="AppBundle\Rot13Transformer" />
209229
230+
<service id="AppBundle\TransformerInterface" alias="AppBundle\Rot13Transformer" />
231+
210232
<service id="AppBundle\TwitterClient" autowire="true" />
211233
</services>
212234
</container>
213235
214236
.. code-block:: php
215237
216238
use AppBundle\Rot13Transformer;
239+
use AppBundle\TransformerInterface;
217240
use AppBundle\TwitterClient;
218241
219242
// ...
220243
$container->register(Rot13Transformer::class);
244+
$container->setAlias(TransformerInterface::class, Rot13Transformer::class);
245+
221246
$container->autowire(TwitterClient::class);
222247
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.
227253

228254
.. _service-autowiring-alias:
229255

230256
Dealing with Multiple Implementations of the Same Type
231257
------------------------------------------------------
232258

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::
236267

237268
namespace AppBundle;
238269

@@ -274,6 +305,9 @@ transformer::
274305
*/
275306
public function tweetAction(Request $request, TwitterClient $twitterClient)
276307
{
308+
// Here the client is automatically injected because it's the default
309+
// implementation
310+
277311
return $this->tweet($request, $twitterClient);
278312
}
279313

@@ -315,6 +349,9 @@ and a Twitter client using it:
315349
services:
316350
AppBundle\Rot13Transformer: ~
317351
352+
# the ``AppBundle\Rot13Transformer`` service will *always* be used
353+
# when ``AppBundle\TransformerInterface`` is detected by the
354+
# autowiring subsystem
318355
AppBundle\TransformerInterface: '@AppBundle\Rot13Transformer'
319356
320357
AppBundle\TwitterClient:
@@ -359,16 +396,16 @@ and a Twitter client using it:
359396
360397
// ...
361398
$container->register(Rot13Transformer::class);
362-
$container->setAlias(TransformerInterface::class, Rot13Transformer::class)
399+
$container->setAlias(TransformerInterface::class, Rot13Transformer::class);
363400
364401
$container->autowire(TwitterClient::class);
365402
$container->autowire(UppercaseTransformer::class);
366403
$container->register('uppercase_twitter_client', TwitterClient::class)
367404
->addArgument(new Reference(UppercaseTransformer::class));
368405
369406
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:
372409

373410
.. code-block:: text
374411

0 commit comments

Comments
 (0)