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

Appearance settings

Commit 7fc8065

Browse filesBrowse files
MathieuMatTheCat
Mathieu
authored andcommitted
1 parent e799862 commit 7fc8065
Copy full SHA for 7fc8065

File tree

Expand file treeCollapse file tree

2 files changed

+122
-7
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+122
-7
lines changed

‎controller/value_resolver.rst

Copy file name to clipboardExpand all lines: controller/value_resolver.rst
+120-5Lines changed: 120 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,83 @@ PSR-7 Objects Resolver:
213213
:class:`Psr\\Http\\Message\\RequestInterface` or :class:`Psr\\Http\\Message\\MessageInterface`.
214214
It requires installing :doc:`the PSR-7 Bridge </components/psr7>` component.
215215

216+
Managing Value Resolvers
217+
------------------------
218+
219+
For each argument, every resolver tagged with ``controller.argument_value_resolver``
220+
will be called until one provides a value. The order in which they are called depends
221+
on their priority. For example, the ``SessionValueResolver`` (priority 50) will be
222+
called before the ``DefaultValueResolver`` (priority -100) which allows to write e.g.
223+
``SessionInterface $session = null`` to get the session if there is one, or ``null``
224+
if there is none.
225+
226+
But what if you *know* there will be a session? In that case every resolver running
227+
before ``SessionValueResolver`` is useless. Worse, some of these could actually
228+
provide a value before ``SessionValueResolver`` has a chance to (don't worry though,
229+
this won't happen with built-in resolvers). Since Symfony 6.3, this kind of issue
230+
can be resolved by leveraging the
231+
:class:`Symfony\\Component\\HttpKernel\\Attribute\\ValueResolver` attribute::
232+
233+
// src/Controller/SessionController.php
234+
namespace App\Controller;
235+
236+
use Symfony\Component\HttpFoundation\Response;
237+
use Symfony\Component\HttpKernel\Attribute\ValueResolver;
238+
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver;
239+
use Symfony\Component\Routing\Annotation\Route;
240+
use Symfony\Component\HttpFoundation\Session\SessionInterface;
241+
242+
class SessionController
243+
{
244+
#[Route('/')]
245+
public function __invoke(
246+
#[ValueResolver(SessionValueResolver::class)]
247+
SessionInterface $session
248+
): Response
249+
{
250+
// ...
251+
}
252+
}
253+
254+
.. versionadded:: 6.3
255+
256+
The ``ValueResolver`` attribute was introduced in Symfony 6.3.
257+
258+
You can target a resolver by passing its name (more on that later) as ``ValueResolver``'s
259+
first argument. For convenience, built-in resolvers' name are their FQCN.
260+
261+
By default, a targeted resolver is "pinned" to the argument holding the
262+
``ValueResolver`` attribute, meaning that only it will be called to provide a value,
263+
and that it will have to.
264+
265+
In the above example the ``DefaultValueResolver`` would never be called, so adding a
266+
default value to ``$session`` would be useless. If we need one, then it is fine not
267+
to use ``ValueResolver``.
268+
But then, what if we want to prevent an hypothetic ``EagerValueResolver`` to provide a
269+
value before ``SessionValueResolver``? Time to use ``ValueResolver``'s second argument!
270+
By passing it to ``true``, you can disable the targeted resolver::
271+
272+
// src/Controller/SessionController.php
273+
namespace App\Controller;
274+
275+
use App\ArgumentResolver\EagerValueResolver;
276+
use Symfony\Component\HttpFoundation\Response;
277+
use Symfony\Component\HttpKernel\Attribute\ValueResolver;
278+
use Symfony\Component\Routing\Annotation\Route;
279+
use Symfony\Component\HttpFoundation\Session\SessionInterface;
280+
281+
class SessionController
282+
{
283+
#[Route('/')]
284+
public function __invoke(
285+
#[ValueResolver(EagerValueResolver::class, disabled: true)]
286+
SessionInterface $session = null
287+
): Response
288+
{
289+
// ...
290+
}
291+
}
292+
216293
Adding a Custom Value Resolver
217294
------------------------------
218295

@@ -297,8 +374,13 @@ When those requirements are met, the method creates a new instance of the
297374
custom value object and returns it as the value for this argument.
298375

299376
That's it! Now all you have to do is add the configuration for the service
300-
container. This can be done by tagging the service with ``controller.argument_value_resolver``
301-
and adding a priority:
377+
container. This can be done by adding one of the following tags to your value resolver.
378+
379+
``controller.argument_value_resolver``
380+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
381+
382+
This tag is automatically added to every service implementing ``ValueResolverInterface``,
383+
but you can set it yourself to change its ``priority`` or ``name`` attributes.
302384

303385
.. configuration-block::
304386

@@ -313,7 +395,9 @@ and adding a priority:
313395
314396
App\ValueResolver\BookingIdValueResolver:
315397
tags:
316-
- { name: controller.argument_value_resolver, priority: 150 }
398+
- controller.argument_value_resolver:
399+
name: booking_id
400+
priority: 150
317401
318402
.. code-block:: xml
319403
@@ -330,7 +414,7 @@ and adding a priority:
330414
<!-- ... -->
331415
332416
<service id="App\ValueResolver\BookingIdValueResolver">
333-
<tag name="controller.argument_value_resolver" priority="150"/>
417+
<tag name="booking_id" priority="150"/>controller.argument_value_resolver</tag>
334418
</service>
335419
</services>
336420
@@ -347,7 +431,7 @@ and adding a priority:
347431
$services = $containerConfigurator->services();
348432
349433
$services->set(BookingIdValueResolver::class)
350-
->tag('controller.argument_value_resolver', ['priority' => 150])
434+
->tag('controller.argument_value_resolver', ['name' => 'booking_id', 'priority' => 150])
351435
;
352436
};
353437
@@ -364,3 +448,34 @@ command to see which argument resolvers are present and in which order they run:
364448
.. code-block:: terminal
365449
366450
$ php bin/console debug:container debug.argument_resolver.inner --show-arguments
451+
452+
You can also configure the name passed to the ``ValueResolver`` attribute to target
453+
your resolver. Otherwise it will default to the service's id.
454+
455+
``controller.targeted_value_resolver``
456+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
457+
458+
Set this tag if you want your resolver to be called only if it is pinned by a
459+
``ValueResolver`` attribute. Like ``controller.argument_value_resolver``, you
460+
can customize the name by which your resolver can be targeted.
461+
462+
As an alternative, you can add the
463+
:class:`Symfony\\Component\\HttpKernel\\Attribute\\AsTargetedValueResolver` attribute
464+
to your resolver and pass your custom name as its first argument::
465+
466+
// src/ValueResolver/IdentifierValueResolver.php
467+
namespace App\ValueResolver;
468+
469+
use Symfony\Component\HttpKernel\Attribute\AsTargetedValueResolver;
470+
use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
471+
472+
#[AsTargetedValueResolver('booking_id')]
473+
class BookingIdValueResolver implements ValueResolverInterface
474+
{
475+
// ...
476+
}
477+
478+
.. versionadded:: 6.3
479+
480+
The ``controller.targeted_value_resolver`` tag and ``AsTargetedValueResolver``
481+
attribute were introduced in Symfony 6.3.

‎reference/attributes.rst

Copy file name to clipboardExpand all lines: reference/attributes.rst
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,13 @@ HttpKernel
5454
~~~~~~~~~~
5555

5656
* :doc:`AsController </controller/service>`
57-
* :class:`Symfony\\Component\\HttpKernel\\Attribute\\AsPinnedValueResolver`
57+
* :ref:`AsTargetedValueResolver <controller-targeted-value-resolver>`
5858
* :ref:`Cache <http-cache-expiration-intro>`
5959
* :ref:`MapDateTime <functionality-shipped-with-the-httpkernel>`
6060
* :ref:`MapQueryParameter <controller_map-request>`
6161
* :ref:`MapQueryString <controller_map-request>`
6262
* :ref:`MapRequestPayload <controller_map-request>`
63-
* :class:`Symfony\\Component\\HttpKernel\\Attribute\\ValueResolver`
63+
* :ref:`ValueResolver <managing-value-resolvers>`
6464
* :ref:`WithHttpStatus <framework_exceptions>`
6565
* :ref:`WithLogLevel <framework_exceptions>`
6666

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.