Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf22dc96

Browse files
Iltar van der Bergwouterj
Iltar van der Berg
authored andcommitted
Added docs about ArgumentValueResolvers
1 parent0db3a92 commitf22dc96

File tree

3 files changed

+221
-0
lines changed

3 files changed

+221
-0
lines changed
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
..index::
2+
single: Controller; Argument Value Resolvers
3+
4+
Extending Action Argument Resolving
5+
===================================
6+
7+
..versionadded::3.1
8+
The ``ArgumentResolver`` and value resolvers were introduced in Symfony 3.1.
9+
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
13+
:class:`Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver`. By
14+
creating and registering custom argument value resolvers, you can extend
15+
this functionality.
16+
17+
Functionality Shipped with the HttpKernel
18+
-----------------------------------------
19+
20+
Symfony ships with four value resolvers in the HttpKernel component:
21+
22+
:class:`Symfony\\Component\\HttpKernel\\Controller\\ArgumentValueResolver\\ArgumentFromAttributeResolver`
23+
Attempts to find a request attribute that matches the name of the argument.
24+
25+
:class:`Symfony\\Component\\HttpKernel\\Controller\\ArgumentValueResolver\\RequestValueResolver`
26+
Injects the current ``Request`` if type-hinted with ``Request``, or a
27+
sub-class thereof.
28+
29+
:class:`Symfony\\Component\\HttpKernel\\Controller\\ArgumentValueResolver\\DefaultValueResolver`
30+
Will set the default value of the argument if present and the argument
31+
is optional.
32+
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.
37+
38+
..note::
39+
40+
Prior to Symfony 3.1, this logic was resolved within the ``ControllerResolver``.
41+
The old functionality is rewritten to the aforementioned value resolvers.
42+
43+
Adding a Custom Value Resolver
44+
------------------------------
45+
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::
49+
50+
namespace AppBundle\Controller;
51+
52+
use AppBundle\Entity\User;
53+
use Symfony\Component\HttpFoundation\Response;
54+
55+
class UserController
56+
{
57+
public function indexAction(User $user)
58+
{
59+
return new Response('<html><body>Hello '.$user->getUsername().'!</body></html>');
60+
}
61+
}
62+
63+
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`.
65+
This interface specifies that you have to implement two methods:
66+
67+
``supports()``
68+
This method is used to check whether the value resolver supports the
69+
given argument. ``resolve()`` will only be executed when this returns ``true``.
70+
``resolve()``
71+
This method will resolve the actual value for the argument. Once the value
72+
is resolved, you must `yield`_ the value to the ``ArgumentResolver``.
73+
74+
Both methods get the ``Request`` object, which is the current request, and an
75+
:class:`Symfony\\Component\\HttpKernel\\ControllerMetadata\\ArgumentMetadata`
76+
instance. This object contains all information retrieved from the method signature
77+
for the current argument.
78+
79+
Now that you know what to do, you can implement this interface. To get the
80+
current ``User``, you need the current security token. This token can be
81+
retrieved from the token storage::
82+
83+
namespace AppBundle\ArgumentValueResolver;
84+
85+
use AppBundle\Entity\User;
86+
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
87+
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
88+
89+
class UserValueResolver implements ArgumentValueResolverInterface
90+
{
91+
private $tokenStorage;
92+
93+
public function __construct(TokenStorageInterface $tokenStorage)
94+
{
95+
$this->tokenStorage = $tokenStorage;
96+
}
97+
98+
public function supports(Request $request, ArgumentMetadata $argument)
99+
{
100+
if (User::class !== $argument->getType()) {
101+
return false;
102+
}
103+
104+
$token = $this->tokenStorage->getToken();
105+
106+
if (!$token instanceof TokenInterface) {
107+
return false;
108+
}
109+
110+
return $token->getUser() instanceof User;
111+
}
112+
113+
public function resolve(Request $request, ArgumentMetadata $argument)
114+
{
115+
yield $this->tokenStorage->getToken()->getUser();
116+
}
117+
}
118+
119+
In order to get the actual ``User`` object in your argument, the given value
120+
must fulfill the following requirements:
121+
122+
* An argument must be type-hinted as ``User`` in your action method signature;
123+
* A security token must be present;
124+
* The value must be an instance of the ``User``.
125+
126+
When all those requirements are met and true is returned, the ``ArgumentResolver``
127+
calls ``resolve()`` with the same values as it called ``supports()``.
128+
129+
That's it! Now all you have to do is add the configuration for the service
130+
container. This can be done by tagging the service with ``controller.argument_resolver``
131+
and adding a priority.
132+
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+
143+
..configuration-block::
144+
145+
..code-block::yaml
146+
147+
# app/config/services.yml
148+
services:
149+
app.value_resolver.user:
150+
class:AppBundle\ArgumentValueResolver\UserValueResolver
151+
arguments:
152+
-'@security.token_storage'
153+
tags:
154+
-{ name: controller.argument_value_resolver, priority: 50 }
155+
156+
..code-block::xml
157+
158+
<!-- app/config/services.xml-->
159+
<?xml version="1.0" encoding="UTF-8" ?>
160+
<containerxmlns="http://symfony.com/schema/dic/services"
161+
xmlns:xsi="'http://www.w3.org/2001/XMLSchema-Instance"
162+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
163+
164+
<services>
165+
<serviceid="app.value_resolver.user"class="AppBundle\ArgumentValueResolver\UserValueResolver">
166+
<argumenttype="service"id="security.token_storage">
167+
<tagname="controller.argument_value_resolver"priority="50" />
168+
</service>
169+
</services>
170+
171+
</container>
172+
173+
..code-block::php
174+
175+
// app/config/services.php
176+
use Symfony\Component\DependencyInjection\Definition;
177+
178+
$defintion = new Definition(
179+
'AppBundle\ArgumentValueResolver\UserValueResolver',
180+
array(new Reference('security.token_storage'))
181+
);
182+
$definition->addTag('controller.argument_value_resolver', array('priority' => 50));
183+
$container->setDefinition('app.value_resolver.user', $definition);
184+
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`.
192+
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::
199+
200+
namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver;
201+
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+
}
218+
219+
.. _`yield`:http://php.net/manual/en/language.generators.syntax.php

‎cookbook/controller/index.rst‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ Controller
77
error_pages
88
service
99
upload_file
10+
argument_value_resolver

‎cookbook/map.rst.inc‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
* :doc:`/cookbook/controller/error_pages`
5757
* :doc:`/cookbook/controller/service`
5858
* :doc:`/cookbook/controller/upload_file`
59+
* :doc:`/cookbook/controller/argument_value_resolver`
5960

6061
***Debugging**
6162

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp