diff --git a/components/http_kernel/introduction.rst b/components/http_kernel/introduction.rst index 2e2ae670da0..5b1acf99050 100644 --- a/components/http_kernel/introduction.rst +++ b/components/http_kernel/introduction.rst @@ -90,6 +90,8 @@ to the events discussed below:: use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\HttpKernel; use Symfony\Component\EventDispatcher\EventDispatcher; + use Symfony\Component\HttpFoundation\RequestStack; + use Symfony\Component\HttpKernel\Controller\ArgumentResolver; use Symfony\Component\HttpKernel\Controller\ControllerResolver; // create the Request object @@ -98,10 +100,12 @@ to the events discussed below:: $dispatcher = new EventDispatcher(); // ... add some event listeners - // create your controller resolver - $resolver = new ControllerResolver(); + // create your controller and argument resolvers + $controllerResolver = new ControllerResolver(); + $argumentResolver = new ArgumentResolver(); + // instantiate the kernel - $kernel = new HttpKernel($dispatcher, $resolver); + $kernel = new HttpKernel($dispatcher, $controllerResolver, new RequestStack(), $argumentResolver); // actually execute the kernel, which turns the request into a response // by dispatching events, calling a controller, and returning the response @@ -118,6 +122,14 @@ See ":ref:`http-kernel-working-example`" for a more concrete implementation. For general information on adding listeners to the events below, see :ref:`http-kernel-creating-listener`. + +.. caution:: + + As of 3.1 the :class:`Symfony\\Component\\Httpkernel\\HttpKernel` accepts a fourth argument, which + must be an instance of :class:`Symfony\\Component\\Httpkernel\\Controller\\ArgumentResolverInterface`. + In 4.0 this argument will become mandatory and the :class:`Symfony\\Component\\Httpkernel\\HttpKernel` + will no longer be able to fall back to the :class:`Symfony\\Component\\Httpkernel\\Controller\\ControllerResolver`. + .. seealso:: There is a wonderful tutorial series on using the HttpKernel component and @@ -225,13 +237,21 @@ This implementation is explained more in the sidebar below:: public function getArguments(Request $request, $controller); } +.. caution:: + + The ``getArguments()`` method in the :class:`Symfony\\Component\\Httpkernel\\Controller\\ControllerResolver` + and respective interface :class:`Symfony\\Component\\Httpkernel\\Controller\\ControllerResolverInterface` + are deprecated as of 3.1 and will be removed in 4.0. You can use the + :class:`Symfony\\Component\\Httpkernel\\Controller\\ArgumentResolver` which uses the + :class:`Symfony\\Component\\Httpkernel\\Controller\\ArgumentResolverInterface` instead. + Internally, the ``HttpKernel::handle`` method first calls :method:`Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface::getController` on the controller resolver. This method is passed the ``Request`` and is responsible for somehow determining and returning a PHP callable (the controller) based on the request's information. -The second method, :method:`Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface::getArguments`, +The second method, :method:`Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolverInterface::getArguments`, will be called after another event - ``kernel.controller`` - is dispatched. .. sidebar:: Resolving the Controller in the Symfony Framework @@ -310,11 +330,11 @@ on the event object that's passed to listeners on this event. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Next, ``HttpKernel::handle`` calls -:method:`Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface::getArguments`. +:method:`Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolverInterface::getArguments`. Remember that the controller returned in ``getController`` is a callable. The purpose of ``getArguments`` is to return the array of arguments that should be passed to that controller. Exactly how this is done is completely -up to your design, though the built-in :class:`Symfony\\Component\\HttpKernel\\Controller\\ControllerResolver` +up to your design, though the built-in :class:`Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver` is a good example. .. image:: /images/components/http_kernel/07-controller-arguments.png @@ -326,7 +346,7 @@ of arguments that should be passed when executing that callable. .. sidebar:: Getting the Controller Arguments in the Symfony Framework Now that you know exactly what the controller callable (usually a method - inside a controller object) is, the ``ControllerResolver`` uses `reflection`_ + inside a controller object) is, the ``ArgumentResolver`` uses `reflection`_ on the callable to return an array of the *names* of each of the arguments. It then iterates over each of these arguments and uses the following tricks to determine which value should be passed for each argument: @@ -338,8 +358,19 @@ of arguments that should be passed when executing that callable. from the ``RouterListener``). b) If the argument in the controller is type-hinted with Symfony's - :class:`Symfony\\Component\\HttpFoundation\\Request` object, then the - ``Request`` is passed in as the value. + :class:`Symfony\\Component\\HttpFoundation\\Request` object, the + ``Request`` is passed in as the value. If you have a custom ``Request`` + class, it will be injected as long as you extend the Symfony ``Request``. + + c) If the function or method argument is `variadic`_ and the ``Request`` + ``attributes`` bag contains and array for that argument, they will all be + available through the `variadic`_ argument. + + This functionality is provided by resolvers implementing the + :class:`Symfony\\Component\\HttpKernel\\Controller\\ArgumentValueResolverInterface`. + There are four implementations which provide the default behavior of Symfony but + customization is the key here. By implementing the ``ArgumentValueResolverInterface`` + yourself and passing this to the ``ArgumentResolver``, you can extend this functionality. .. _component-http-kernel-calling-controller: @@ -612,47 +643,52 @@ A full Working Example ---------------------- When using the HttpKernel component, you're free to attach any listeners -to the core events and use any controller resolver that implements the -:class:`Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface`. -However, the HttpKernel component comes with some built-in listeners and -a built-in ControllerResolver that can be used to create a working example:: +to the core events, use any controller resolver that implements the +:class:`Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface` and +use any argument resolver that implements the +:class:`Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolverInterface`. +However, the HttpKernel component comes with some built-in listeners and everything +else that can be used to create a working example:: - use Symfony\Component\HttpFoundation\Request; - use Symfony\Component\HttpFoundation\RequestStack; - use Symfony\Component\HttpFoundation\Response; - use Symfony\Component\HttpKernel\HttpKernel; - use Symfony\Component\EventDispatcher\EventDispatcher; - use Symfony\Component\HttpKernel\Controller\ControllerResolver; - use Symfony\Component\HttpKernel\EventListener\RouterListener; - use Symfony\Component\Routing\RouteCollection; - use Symfony\Component\Routing\Route; - use Symfony\Component\Routing\Matcher\UrlMatcher; - use Symfony\Component\Routing\RequestContext; - - $routes = new RouteCollection(); - $routes->add('hello', new Route('/hello/{name}', array( - '_controller' => function (Request $request) { - return new Response( - sprintf("Hello %s", $request->get('name')) - ); - } - ) - )); + use Symfony\Component\EventDispatcher\EventDispatcher; + use Symfony\Component\HttpFoundation\Request; + use Symfony\Component\HttpFoundation\RequestStack; + use Symfony\Component\HttpFoundation\Response; + use Symfony\Component\HttpKernel\Controller\ArgumentResolver; + use Symfony\Component\HttpKernel\Controller\ControllerResolver; + use Symfony\Component\HttpKernel\EventListener\RouterListener; + use Symfony\Component\HttpKernel\HttpKernel; + use Symfony\Component\Routing\Matcher\UrlMatcher; + use Symfony\Component\Routing\RequestContext; + use Symfony\Component\Routing\Route; + use Symfony\Component\Routing\RouteCollection; - $request = Request::createFromGlobals(); + $routes = new RouteCollection(); + $routes->add('hello', new Route('/hello/{name}', array( + '_controller' => function (Request $request) { + return new Response( + sprintf("Hello %s", $request->get('name')) + ); + }) + )); - $matcher = new UrlMatcher($routes, new RequestContext()); + $request = Request::createFromGlobals(); - $dispatcher = new EventDispatcher(); - $dispatcher->addSubscriber(new RouterListener($matcher, new RequestStack())); + $matcher = new UrlMatcher($routes, new RequestContext()); - $resolver = new ControllerResolver(); - $kernel = new HttpKernel($dispatcher, $resolver); + $dispatcher = new EventDispatcher(); + $dispatcher->addSubscriber(new RouterListener($matcher, new RequestStack())); - $response = $kernel->handle($request); - $response->send(); + $controllerResolver = new ControllerResolver(); + $argumentResolver = new ArgumentResolver(); + + $kernel = new HttpKernel($dispatcher, $controllerResolver, new RequestStack(), $argumentResolver); + + $response = $kernel->handle($request); + $response->send(); + + $kernel->terminate($request, $response); - $kernel->terminate($request, $response); .. _http-kernel-sub-requests: @@ -716,3 +752,4 @@ look like this:: .. _`@ParamConverter`: https://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/converters.html .. _`@Template`: https://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/view.html .. _`EmailSenderListener`: https://github.com/symfony/swiftmailer-bundle/blob/master/EventListener/EmailSenderListener.php +.. _variadic: http://php.net/manual/en/functions.arguments.php diff --git a/create_framework/dependency_injection.rst b/create_framework/dependency_injection.rst index 36fa99ffd84..691d5f7a61d 100644 --- a/create_framework/dependency_injection.rst +++ b/create_framework/dependency_injection.rst @@ -9,9 +9,10 @@ to it:: // example.com/src/Simplex/Framework.php namespace Simplex; + use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Routing; + use Symfony\Component\HttpFoundation; use Symfony\Component\HttpKernel; - use Symfony\Component\EventDispatcher\EventDispatcher; class Framework extends HttpKernel\HttpKernel { @@ -19,13 +20,15 @@ to it:: { $context = new Routing\RequestContext(); $matcher = new Routing\Matcher\UrlMatcher($routes, $context); - $resolver = new HttpKernel\Controller\ControllerResolver(); + + $controllerResolver = new HttpKernel\Controller\ControllerResolver(); + $argumentResolver = new HttpKernel\Controller\ArgumentResolver(); $dispatcher = new EventDispatcher(); $dispatcher->addSubscriber(new HttpKernel\EventListener\RouterListener($matcher)); $dispatcher->addSubscriber(new HttpKernel\EventListener\ResponseListener('UTF-8')); - parent::__construct($dispatcher, $resolver); + parent::__construct($dispatcher, $controllerResolver, new RequestStack(), $argumentResolver); } } @@ -101,7 +104,8 @@ Create a new file to host the dependency injection container configuration:: ->setArguments(array($routes, new Reference('context'))) ; $sc->register('request_stack', 'Symfony\Component\HttpFoundation\RequestStack'); - $sc->register('resolver', 'Symfony\Component\HttpKernel\Controller\ControllerResolver'); + $sc->register('controller_resolver', 'Symfony\Component\HttpKernel\Controller\ControllerResolver'); + $sc->register('argument_resolver', 'Symfony\Component\HttpKernel\Controller\ArgumentResolver'); $sc->register('listener.router', 'Symfony\Component\HttpKernel\EventListener\RouterListener') ->setArguments(array(new Reference('matcher'), new Reference('request_stack'))) @@ -118,7 +122,12 @@ Create a new file to host the dependency injection container configuration:: ->addMethodCall('addSubscriber', array(new Reference('listener.exception'))) ; $sc->register('framework', 'Simplex\Framework') - ->setArguments(array(new Reference('dispatcher'), new Reference('resolver'))) + ->setArguments(array( + new Reference('dispatcher'), + new Reference('controller_resolver'), + new Reference('request_stack'), + new Reference('argument_resolver'), + )) ; return $sc; diff --git a/create_framework/event_dispatcher.rst b/create_framework/event_dispatcher.rst index 3964cf5ae46..679359c620a 100644 --- a/create_framework/event_dispatcher.rst +++ b/create_framework/event_dispatcher.rst @@ -36,24 +36,27 @@ the Response instance:: // example.com/src/Simplex/Framework.php namespace Simplex; + use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; - use Symfony\Component\Routing\Matcher\UrlMatcherInterface; - use Symfony\Component\Routing\Exception\ResourceNotFoundException; + use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; - use Symfony\Component\EventDispatcher\EventDispatcher; + use Symfony\Component\Routing\Exception\ResourceNotFoundException; + use Symfony\Component\Routing\Matcher\UrlMatcherInterface; class Framework { - private $matcher; - private $resolver; private $dispatcher; + private $matcher; + private $controllerResolver; + private $argumentResolver; - public function __construct(EventDispatcher $dispatcher, UrlMatcherInterface $matcher, ControllerResolverInterface $resolver) + public function __construct(EventDispatcher $dispatcher, UrlMatcherInterface $matcher, ControllerResolverInterface $controllerResolver, ArgumentResolverInterface $argumentResolver) { - $this->matcher = $matcher; - $this->resolver = $resolver; $this->dispatcher = $dispatcher; + $this->matcher = $matcher; + $this->controllerResolver = $controllerResolver; + $this->argumentResolver = $argumentResolver; } public function handle(Request $request) @@ -63,8 +66,8 @@ the Response instance:: try { $request->attributes->add($this->matcher->match($request->getPathInfo())); - $controller = $this->resolver->getController($request); - $arguments = $this->resolver->getArguments($request, $controller); + $controller = $this->controllerResolver->getController($request); + $arguments = $this->argumentResolver->getArguments($request, $controller); $response = call_user_func_array($controller, $arguments); } catch (ResourceNotFoundException $e) { diff --git a/create_framework/http_kernel_controller_resolver.rst b/create_framework/http_kernel_controller_resolver.rst index c0cf260cf0b..147395bb88a 100644 --- a/create_framework/http_kernel_controller_resolver.rst +++ b/create_framework/http_kernel_controller_resolver.rst @@ -43,10 +43,10 @@ component: $ composer require symfony/http-kernel -The HttpKernel component has many interesting features, but the one we need -right now is the *controller resolver*. A controller resolver knows how to -determine the controller to execute and the arguments to pass to it, based on -a Request object. All controller resolvers implement the following interface:: +The HttpKernel component has many interesting features, but the ones we need +right now are the *controller resolver* and *argument resolver*. A controller resolver knows how to +determine the controller to execute and the argument resolver determines the arguments to pass to it, +based on a Request object. All controller resolvers implement the following interface:: namespace Symfony\Component\HttpKernel\Controller; @@ -58,6 +58,14 @@ a Request object. All controller resolvers implement the following interface:: function getArguments(Request $request, $controller); } +.. caution:: + + The ``getArguments()`` method in the :class:`Symfony\\Component\\Httpkernel\\Controller\\ControllerResolver` + and respective interface :class:`Symfony\\Component\\Httpkernel\\Controller\\ControllerResolverInterface` + are deprecated as of 3.1 and will be removed in 4.0. You can use the + :class:`Symfony\\Component\\Httpkernel\\Controller\\ArgumentResolver` which uses the + :class:`Symfony\\Component\\Httpkernel\\Controller\\ArgumentResolverInterface` instead. + The ``getController()`` method relies on the same convention as the one we have defined earlier: the ``_controller`` request attribute must contain the controller associated with the Request. Besides the built-in PHP callbacks, @@ -74,10 +82,11 @@ resolver from HttpKernel:: use Symfony\Component\HttpKernel; - $resolver = new HttpKernel\Controller\ControllerResolver(); + $controllerResolver = new HttpKernel\Controller\ControllerResolver(); + $argumentResolver = new HttpKernel\Controller\ArgumentResolver(); - $controller = $resolver->getController($request); - $arguments = $resolver->getArguments($request, $controller); + $controller = $controllerResolver->getController($request); + $arguments = $argumentResolver->getArguments($request, $controller); $response = call_user_func_array($controller, $arguments); @@ -140,14 +149,12 @@ method is not defined, an argument has no matching attribute, ...). .. note:: - With the great flexibility of the default controller resolver, you might - wonder why someone would want to create another one (why would there be an - interface if not?). Two examples: in Symfony, ``getController()`` is - enhanced to support - :doc:`controllers as services `; and in - `FrameworkExtraBundle`_, ``getArguments()`` is enhanced to support - parameter converters, where request attributes are converted to objects - automatically. + With the great flexibility of the default controller resolver and argument + resolver, you might wonder why someone would want to create another one + (why would there be an interface if not?). Two examples: in Symfony, + ``getController()`` is enhanced to support :doc:`controllers as services `; + and ``getArguments()`` provides an extension point to alter or enhance + the resolving of arguments. Let's conclude with the new version of our framework:: @@ -174,13 +181,18 @@ Let's conclude with the new version of our framework:: $context = new Routing\RequestContext(); $context->fromRequest($request); $matcher = new Routing\Matcher\UrlMatcher($routes, $context); - $resolver = new HttpKernel\Controller\ControllerResolver(); + + $controllerResolver = new HttpKernel\Controller\ControllerResolver(); + $argumentResolver = new HttpKernel\Controller\ArgumentResolver(); + + $controller = $controllerResolver->getController($request); + $arguments = $argumentResolver->getArguments($request, $controller); try { $request->attributes->add($matcher->match($request->getPathInfo())); - $controller = $resolver->getController($request); - $arguments = $resolver->getArguments($request, $controller); + $controller = $controllerResolver->getController($request); + $arguments = $argumentResolver->getArguments($request, $controller); $response = call_user_func_array($controller, $arguments); } catch (Routing\Exception\ResourceNotFoundException $e) { @@ -192,7 +204,7 @@ Let's conclude with the new version of our framework:: $response->send(); Think about it once more: our framework is more robust and more flexible than -ever and it still has less than 40 lines of code. +ever and it still has less than 50 lines of code. .. _`reflection`: http://php.net/reflection .. _`FrameworkExtraBundle`: http://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/converters.html diff --git a/create_framework/http_kernel_httpkernel_class.rst b/create_framework/http_kernel_httpkernel_class.rst index 5b4aba5556b..890369979d1 100644 --- a/create_framework/http_kernel_httpkernel_class.rst +++ b/create_framework/http_kernel_httpkernel_class.rst @@ -36,24 +36,27 @@ And the new front controller:: // example.com/web/front.php require_once __DIR__.'/../vendor/autoload.php'; + use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\HttpFoundation\Request; + use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; - use Symfony\Component\Routing; use Symfony\Component\HttpKernel; - use Symfony\Component\EventDispatcher\EventDispatcher; - use Symfony\Component\HttpFoundation\RequestStack; + use Symfony\Component\Routing; $request = Request::createFromGlobals(); + $requestStack = new RequestStack(); $routes = include __DIR__.'/../src/app.php'; $context = new Routing\RequestContext(); $matcher = new Routing\Matcher\UrlMatcher($routes, $context); - $resolver = new HttpKernel\Controller\ControllerResolver(); + + $controllerResolver = new HttpKernel\Controller\ControllerResolver(); + $argumentResolver = new HttpKernel\Controller\ArgumentResolver(); $dispatcher = new EventDispatcher(); - $dispatcher->addSubscriber(new HttpKernel\EventListener\RouterListener($matcher, new RequestStack())); + $dispatcher->addSubscriber(new HttpKernel\EventListener\RouterListener($matcher, $requestStack)); - $framework = new Simplex\Framework($dispatcher, $resolver); + $framework = new Simplex\Framework($dispatcher, $controllerResolver, $requestStack, $argumentResolver); $response = $framework->handle($request); $response->send(); @@ -151,9 +154,8 @@ only if needed:: namespace Simplex; use Symfony\Component\EventDispatcher\EventSubscriberInterface; - use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent; - use Symfony\Component\HttpKernel\KernelEvents; + use Symfony\Component\HttpFoundation\Response; class StringResponseListener implements EventSubscriberInterface { @@ -168,7 +170,7 @@ only if needed:: public static function getSubscribedEvents() { - return array(KernelEvents::VIEW => 'onView'); + return array('kernel.view' => 'onView'); } } diff --git a/create_framework/separation_of_concerns.rst b/create_framework/separation_of_concerns.rst index 9340e3b6519..ee3fe283ef1 100644 --- a/create_framework/separation_of_concerns.rst +++ b/create_framework/separation_of_concerns.rst @@ -2,7 +2,7 @@ The Separation of Concerns ========================== One down-side of our framework right now is that we need to copy and paste the -code in ``front.php`` each time we create a new website. 40 lines of code is +code in ``front.php`` each time we create a new website. 60 lines of code is not that much, but it would be nice if we could wrap this code into a proper class. It would bring us better *reusability* and easier testing to name just a few benefits. @@ -20,19 +20,22 @@ request handling logic into its own ``Simplex\\Framework`` class:: use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; - use Symfony\Component\Routing\Matcher\UrlMatcher; - use Symfony\Component\Routing\Exception\ResourceNotFoundException; + use Symfony\Component\HttpKernel\Controller\ArgumentResolver; use Symfony\Component\HttpKernel\Controller\ControllerResolver; + use Symfony\Component\Routing\Exception\ResourceNotFoundException; + use Symfony\Component\Routing\Matcher\UrlMatcher; class Framework { protected $matcher; - protected $resolver; + protected $controllerResolver; + protected $argumentResolver; - public function __construct(UrlMatcher $matcher, ControllerResolver $resolver) + public function __construct(UrlMatcher $matcher, ControllerResolver $controllerResolver, ArgumentResolver $argumentResolver) { $this->matcher = $matcher; - $this->resolver = $resolver; + $this->controllerResolver = $controllerResolver; + $this->argumentResolver = $argumentResolver; } public function handle(Request $request) @@ -42,8 +45,8 @@ request handling logic into its own ``Simplex\\Framework`` class:: try { $request->attributes->add($this->matcher->match($request->getPathInfo())); - $controller = $this->resolver->getController($request); - $arguments = $this->resolver->getArguments($request, $controller); + $controller = $this->controllerResolver->getController($request); + $arguments = $this->argumentResolver->getArguments($request, $controller); return call_user_func_array($controller, $arguments); } catch (ResourceNotFoundException $e) { @@ -64,9 +67,11 @@ And update ``example.com/web/front.php`` accordingly:: $context = new Routing\RequestContext(); $matcher = new Routing\Matcher\UrlMatcher($routes, $context); - $resolver = new HttpKernel\Controller\ControllerResolver(); - $framework = new Simplex\Framework($matcher, $resolver); + $controllerResolver = new ControllerResolver(); + $argumentResolver = new ArgumentResolver(); + + $framework = new Simplex\Framework($matcher, $controllerResolver, new RequestStack(), $argumentResolver); $response = $framework->handle($request); $response->send(); @@ -142,7 +147,7 @@ To sum up, here is the new file layout: example.com ├── composer.json - ├── composer.lock + ├── composer.lock ├── src │ ├── app.php │ └── Simplex diff --git a/reference/dic_tags.rst b/reference/dic_tags.rst index 5a9fba64137..7db13cd1109 100644 --- a/reference/dic_tags.rst +++ b/reference/dic_tags.rst @@ -24,6 +24,7 @@ Tag Name Usage `assetic.templating.twig`_ Remove this service if Twig templating is disabled `auto_alias`_ Define aliases based on the value of container parameters `console.command`_ Add a command +`controller.argument_value_resolver`_ Register a value resolver for controller arguments such as ``Request`` `data_collector`_ Create a class that collects custom data for the profiler `doctrine.event_listener`_ Add a Doctrine event listener `doctrine.event_subscriber`_ Add a Doctrine event subscriber @@ -350,6 +351,15 @@ console.command For details on registering your own commands in the service container, read :ref:`the cookbook article`. +controller.argument_value_resolver +---------------------------------- + +**Purpose**: Register a value resolver for controller arguments such as ``Request`` + +Value resolvers implement the :class:`Symfony\\Component\\HttpKernel\\Controller\\ArgumentValueResolverInterface` +and are used to resolve argument values for controllers as described here: +:doc:`/cookbook/controller/argument_value_resolver`. + data_collector --------------