Skip to content

Commit 66ce882

Browse files
committed
[#6438] Fix class names and shorten article after merging
1 parent ae73303 commit 66ce882

File tree

1 file changed

+47
-65
lines changed

1 file changed

+47
-65
lines changed

cookbook/controller/argument_value_resolver.rst

+47-65
Original file line numberDiff line numberDiff line change
@@ -7,33 +7,34 @@ Extending Action Argument Resolving
77
.. versionadded:: 3.1
88
The ``ArgumentResolver`` and value resolvers were introduced in Symfony 3.1.
99

10-
In the book, you've learned that you can get the :class:`Symfony\\Component\\HttpFoundation\\Request`
11-
object via an argument in your controller. This argument has to be type-hinted
12-
by the ``Request`` class in order to be recognized. This is done via the
10+
In the book, you've learned that you can get the
11+
:class:`Symfony\\Component\\HttpFoundation\\Request` object via an argument in
12+
your controller. This argument has to be type-hinted by the ``Request`` class
13+
in order to be recognized. This is done via the
1314
:class:`Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver`. By
14-
creating and registering custom argument value resolvers, you can extend
15-
this functionality.
15+
creating and registering custom argument value resolvers, you can extend this
16+
functionality.
1617

1718
Functionality Shipped with the HttpKernel
1819
-----------------------------------------
1920

2021
Symfony ships with four value resolvers in the HttpKernel component:
2122

22-
:class:`Symfony\\Component\\HttpKernel\\Controller\\ArgumentValueResolver\\ArgumentFromAttributeResolver`
23+
:class:`Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestAttributeValueResolver`
2324
Attempts to find a request attribute that matches the name of the argument.
2425

25-
:class:`Symfony\\Component\\HttpKernel\\Controller\\ArgumentValueResolver\\RequestValueResolver`
26-
Injects the current ``Request`` if type-hinted with ``Request``, or a
27-
sub-class thereof.
26+
:class:`Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\RequestValueResolver`
27+
Injects the current ``Request`` if type-hinted with ``Request`` or a class
28+
extending ``Request``.
2829

29-
:class:`Symfony\\Component\\HttpKernel\\Controller\\ArgumentValueResolver\\DefaultValueResolver`
30+
:class:`Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\DefaultValueResolver`
3031
Will set the default value of the argument if present and the argument
3132
is optional.
3233

33-
:class:`Symfony\\Component\\HttpKernel\\Controller\\ArgumentValueResolver\\VariadicValueResolver`
34-
Verifies in the request if your data is an array and will add all of
35-
them to the argument list. When the action is called, the last (variadic)
36-
argument will contain all the values of this array.
34+
:class:`Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver\\VariadicValueResolver`
35+
Verifies if the request data is an array and will add all of them to the
36+
argument list. When the action is called, the last (variadic) argument will
37+
contain all the values of this array.
3738

3839
.. note::
3940

@@ -43,9 +44,10 @@ Symfony ships with four value resolvers in the HttpKernel component:
4344
Adding a Custom Value Resolver
4445
------------------------------
4546

46-
Adding a new value resolver requires one class and one service defintion.
47-
In the next example, you'll create a value resolver to inject the ``User``
48-
object from the security system. Given you write the following action::
47+
Adding a new value resolver requires creatign one class and one service
48+
definition. In the next example, you'll create a value resolver to inject the
49+
``User`` object from the security system. Given you write the following
50+
controller::
4951

5052
namespace AppBundle\Controller;
5153

@@ -56,12 +58,13 @@ object from the security system. Given you write the following action::
5658
{
5759
public function indexAction(User $user)
5860
{
59-
return new Response('<html><body>Hello '.$user->getUsername().'!</body></html>');
61+
return new Response('Hello '.$user->getUsername().'!');
6062
}
6163
}
6264

6365
Somehow you will have to get the ``User`` object and inject it into the controller.
64-
This can be done by implementing the :class:`Symfony\\Component\\HttpKernel\\Controller\\ArgumentValueResolverInterface`.
66+
This can be done by implementing the
67+
:class:`Symfony\\Component\\HttpKernel\\Controller\\ArgumentValueResolverInterface`.
6568
This interface specifies that you have to implement two methods:
6669

6770
``supports()``
@@ -80,7 +83,8 @@ Now that you know what to do, you can implement this interface. To get the
8083
current ``User``, you need the current security token. This token can be
8184
retrieved from the token storage::
8285

83-
namespace AppBundle\ArgumentValueResolver;
86+
// src/AppBundle/ArgumentResolver/UserValueResolver.php
87+
namespace AppBundle\ArgumentResolver;
8488

8589
use AppBundle\Entity\User;
8690
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
@@ -123,31 +127,22 @@ must fulfill the following requirements:
123127
* A security token must be present;
124128
* The value must be an instance of the ``User``.
125129

126-
When all those requirements are met and true is returned, the ``ArgumentResolver``
127-
calls ``resolve()`` with the same values as it called ``supports()``.
130+
When all those requirements are met and ``true`` is returned, the
131+
``ArgumentResolver`` calls ``resolve()`` with the same values as it called
132+
``supports()``.
128133

129134
That's it! Now all you have to do is add the configuration for the service
130135
container. This can be done by tagging the service with ``controller.argument_resolver``
131136
and adding a priority.
132137

133-
.. note::
134-
135-
While adding a priority is optional, it's recommended to add one to
136-
make sure the expected value is injected. The ``ArgumentFromAttributeResolver``
137-
has a priority of 100. As this one is responsible for fetching attributes
138-
from the ``Request``, it's also recommended to trigger your custom value
139-
resolver with a lower priority. This makes sure the argument resolvers
140-
are not triggered in (e.g.) subrequests if you pass your user along:
141-
``{{ render(controller('AppBundle:User:index', {'user', app.user})) }}``.
142-
143138
.. configuration-block::
144139

145140
.. code-block:: yaml
146141
147142
# app/config/services.yml
148143
services:
149144
app.value_resolver.user:
150-
class: AppBundle\ArgumentValueResolver\UserValueResolver
145+
class: AppBundle\ArgumentResolver\UserValueResolver
151146
arguments:
152147
- '@security.token_storage'
153148
tags:
@@ -162,7 +157,9 @@ and adding a priority.
162157
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
163158
164159
<services>
165-
<service id="app.value_resolver.user" class="AppBundle\ArgumentValueResolver\UserValueResolver">
160+
<service id="app.value_resolver.user"
161+
class="AppBundle\ArgumentResolver\UserValueResolver"
162+
>
166163
<argument type="service" id="security.token_storage">
167164
<tag name="controller.argument_value_resolver" priority="50" />
168165
</service>
@@ -176,44 +173,29 @@ and adding a priority.
176173
use Symfony\Component\DependencyInjection\Definition;
177174
178175
$defintion = new Definition(
179-
'AppBundle\ArgumentValueResolver\UserValueResolver',
176+
'AppBundle\ArgumentResolver\UserValueResolver',
180177
array(new Reference('security.token_storage'))
181178
);
182179
$definition->addTag('controller.argument_value_resolver', array('priority' => 50));
183180
$container->setDefinition('app.value_resolver.user', $definition);
184181
185-
Creating an Optional User Resolver
186-
----------------------------------
187-
188-
When you want your user to be optional, e.g. when your page is behind a
189-
firewall that also allows anonymous authentication, you might not always
190-
have a security user. To get this to work, you only have to change your
191-
method signature to `UserInterface $user = null`.
182+
While adding a priority is optional, it's recommended to add one to make sure
183+
the expected value is injected. The ``RequestAttributeValueResolver`` has a
184+
priority of 100. As this one is responsible for fetching attributes from the
185+
``Request``, it's recommended to trigger your custom value resolver with a
186+
lower priority. This makes sure the argument resolvers are not triggered when
187+
the attribute is present. For instance, when passing the user along a
188+
subrequests.
192189

193-
When you take the ``UserValueResolver`` from the previous example, you can
194-
see there is no logic in case of failure to comply to the requirements. Default
195-
values are defined in the signature and are available in the ``ArgumentMetadata``.
196-
When a default value is available and there are no resolvers that support
197-
the given value, the ``DefaultValueResolver`` is triggered. This Resolver
198-
takes the default value of your argument and yields it to the argument list::
190+
.. tip::
199191

200-
namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver;
192+
As you see in the ``UserValueResolver::supports()`` method, the user may
193+
not be available (e.g. when the controller is not behind a firewall). In
194+
these cases, the resolver will not be executed. If no argument value is
195+
resolved, an exception will be throwed.
201196

202-
use Symfony\Component\HttpFoundation\Request;
203-
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
204-
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
205-
206-
final class DefaultValueResolver implements ArgumentValueResolverInterface
207-
{
208-
public function supports(Request $request, ArgumentMetadata $argument)
209-
{
210-
return $argument->hasDefaultValue();
211-
}
212-
213-
public function resolve(Request $request, ArgumentMetadata $argument)
214-
{
215-
yield $argument->getDefaultValue();
216-
}
217-
}
197+
To prevent this, you can add a default value in the controller (e.g. ``User
198+
$user = null``). The ``DefaultValueResolver`` is executed as last resolver
199+
and will use the default value if no value is resolved already.
218200

219201
.. _`yield`: http://php.net/manual/en/language.generators.syntax.php

0 commit comments

Comments
 (0)