@@ -85,11 +85,22 @@ is really simple and involves creating an
8585:doc: `event dispatcher </components/event_dispatcher/introduction >` and a
8686:ref: `controller resolver <component-http-kernel-resolve-controller >` (explained
8787below). To complete your working kernel, you'll add more event listeners
88- to the events discussed below::
88+ to the events discussed below
89+
90+ ..caution ::
91+
92+ As of 3.1 the:class: `Symfony\\ Component\\ Httpkernel\\ HttpKernel ` accepts a fourth argument, which
93+ should be an instance of:class: `Symfony\\ Component\\ Httpkernel\\ Controller\\ ArgumentResolverInterface `.
94+ In 4.0 this argument will become mandatory and the:class: `Symfony\\ Component\\ Httpkernel\\ HttpKernel `
95+ will no longer be able to fall back to the:class: `Symfony\\ Component\\ Httpkernel\\ Controller\\ ControllerResolver `.
96+
97+ ..code-block ::php
8998
9099 use Symfony\Component\HttpFoundation\Request;
91100 use Symfony\Component\HttpKernel\HttpKernel;
92101 use Symfony\Component\EventDispatcher\EventDispatcher;
102+ use Symfony\Component\HttpFoundation\RequestStack;
103+ use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
93104 use Symfony\Component\HttpKernel\Controller\ControllerResolver;
94105
95106 // create the Request object
@@ -98,10 +109,16 @@ to the events discussed below::
98109 $dispatcher = new EventDispatcher();
99110 // ... add some event listeners
100111
101- // create your controller resolver
102- $resolver = new ControllerResolver();
112+ $valueResolvers = [
113+ // ... add some implementations of ArgumentValueResolverInterface
114+ ];
115+
116+ // create your controller and argument resolver
117+ $controllerResolver = new ControllerResolver();
118+ $argumentResolver = new ArgumentResolver($argumentMetadataFactory, $valueResolvers);
119+
103120 // instantiate the kernel
104- $kernel = new HttpKernel($dispatcher, $resolver );
121+ $kernel = new HttpKernel($dispatcher, $controllerResolver, new RequestStack(), $argumentResolver );
105122
106123 // actually execute the kernel, which turns the request into a response
107124 // by dispatching events, calling a controller, and returning the response
@@ -212,7 +229,19 @@ Your job is to create a class that implements the interface and fill in its
212229two methods: ``getController `` and ``getArguments ``. In fact, one default
213230implementation already exists, which you can use directly or learn from:
214231:class: `Symfony\\ Component\\ HttpKernel\\ Controller\\ ControllerResolver `.
215- This implementation is explained more in the sidebar below::
232+ This implementation is explained more in the sidebar below
233+
234+
235+ ..caution ::
236+
237+ The `getArguments() ` method in the:class: `Symfony\\ Component\\ Httpkernel\\ Controller\\ ControllerResolver `
238+ and respective interface:class: `Symfony\\ Component\\ Httpkernel\\ Controller\\ ControllerResolverInterface `
239+ are deprecated as of 3.1 and will be removed in 4.0. You can use the
240+ :class: `Symfony\\ Component\\ Httpkernel\\ Controller\\ ArgumentResolver ` which uses the
241+ :class: `Symfony\\ Component\\ Httpkernel\\ Controller\\ ArgumentResolverInterface ` instead.
242+
243+
244+ ..code-block ::php
216245
217246 namespace Symfony\Component\HttpKernel\Controller;
218247
@@ -231,7 +260,7 @@ on the controller resolver. This method is passed the ``Request`` and is respons
231260for somehow determining and returning a PHP callable (the controller) based
232261on the request's information.
233262
234- The second method,:method: `Symfony\\ Component\\ HttpKernel\\ Controller\\ ControllerResolverInterface ::getArguments `,
263+ The second method,:method: `Symfony\\ Component\\ HttpKernel\\ Controller\\ ArgumentResolverInterface ::getArguments `,
235264will be called after another event - ``kernel.controller `` - is dispatched.
236265
237266..sidebar ::Resolving the Controller in the Symfony Framework
@@ -310,11 +339,11 @@ on the event object that's passed to listeners on this event.
310339~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
311340
312341Next, ``HttpKernel::handle `` calls
313- :method: `Symfony\\ Component\\ HttpKernel\\ Controller\\ ControllerResolverInterface ::getArguments `.
342+ :method: `Symfony\\ Component\\ HttpKernel\\ Controller\\ ArgumentResolverInterface ::getArguments `.
314343Remember that the controller returned in ``getController `` is a callable.
315344The purpose of ``getArguments `` is to return the array of arguments that
316345should be passed to that controller. Exactly how this is done is completely
317- up to your design, though the built-in:class: `Symfony\\ Component\\ HttpKernel\\ Controller\\ ControllerResolver `
346+ up to your design, though the built-in:class: `Symfony\\ Component\\ HttpKernel\\ Controller\\ ArgumentResolver `
318347is a good example.
319348
320349..image ::/images/components/http_kernel/07-controller-arguments.png
@@ -326,7 +355,7 @@ of arguments that should be passed when executing that callable.
326355..sidebar ::Getting the Controller Arguments in the Symfony Framework
327356
328357 Now that you know exactly what the controller callable (usually a method
329- inside a controller object) is, the ``ControllerResolver `` uses `reflection `_
358+ inside a controller object) is, the ``ArgumentResolver `` uses `reflection `_
330359 on the callable to return an array of the *names * of each of the arguments.
331360 It then iterates over each of these arguments and uses the following tricks
332361 to determine which value should be passed for each argument:
@@ -339,7 +368,18 @@ of arguments that should be passed when executing that callable.
339368
340369 b) If the argument in the controller is type-hinted with Symfony's
341370:class: `Symfony\\ Component\\ HttpFoundation\\ Request ` object, then the
342- ``Request `` is passed in as the value.
371+ ``Request `` is passed in as the value. If you have a custom class extending
372+ the ``Request ``, this is also accepted.
373+
374+ c) If the function or method argument is `variadic `_ and the ``Request ``
375+ ``attributes `` bag contains and array for that argument, they will all be
376+ available through the `variadic `_ argument.
377+
378+ This functionality is provided by resolvers implementing the
379+ :class: `Symfony\\ Component\\ HttpKernel\\ Controller\\ ArgumentValueResolverInterface `.
380+ There are four implementations which provide the default behavior of Symfony but
381+ customization is the key here. By implementing the ``ArgumentValueResolverInterface ``
382+ yourself and passing this to the ``ArgumentResolver ``, you can extend this functionality.
343383
344384.. _component-http-kernel-calling-controller :
345385
@@ -612,47 +652,64 @@ A full Working Example
612652----------------------
613653
614654When using the HttpKernel component, you're free to attach any listeners
615- to the core events and use any controller resolver that implements the
616- :class: `Symfony\\ Component\\ HttpKernel\\ Controller\\ ControllerResolverInterface `.
617- However, the HttpKernel component comes with some built-in listeners and
618- a built-in ControllerResolver that can be used to create a working example::
655+ to the core events, use any controller resolver that implements the
656+ :class: `Symfony\\ Component\\ HttpKernel\\ Controller\\ ControllerResolverInterface ` and
657+ use any argument resolver that implements the
658+ :class: `Symfony\\ Component\\ HttpKernel\\ Controller\\ ArgumentResolverInterface `.
659+ However, the HttpKernel component comes with some built-in listeners, and everything
660+ else that can be used to create a working example::
661+
662+ use Symfony\Component\EventDispatcher\EventDispatcher;
663+ use Symfony\Component\HttpFoundation\Request;
664+ use Symfony\Component\HttpFoundation\RequestStack;
665+ use Symfony\Component\HttpFoundation\Response;
666+ use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
667+ use Symfony\Component\HttpKernel\Controller\ArgumentValueResolver\ArgumentFromAttributeResolver;
668+ use Symfony\Component\HttpKernel\Controller\ArgumentValueResolver\DefaultArgumentValueResolver;
669+ use Symfony\Component\HttpKernel\Controller\ArgumentValueResolver\RequestResolver;
670+ use Symfony\Component\HttpKernel\Controller\ArgumentValueResolver\VariadicArgumentValueResolver;
671+ use Symfony\Component\HttpKernel\Controller\ControllerResolver;
672+ use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory;
673+ use Symfony\Component\HttpKernel\EventListener\RouterListener;
674+ use Symfony\Component\HttpKernel\HttpKernel;
675+ use Symfony\Component\Routing\Matcher\UrlMatcher;
676+ use Symfony\Component\Routing\RequestContext;
677+ use Symfony\Component\Routing\Route;
678+ use Symfony\Component\Routing\RouteCollection;
679+
680+ $routes = new RouteCollection();
681+ $routes->add('hello', new Route('/hello/{name}', array(
682+ '_controller' => function (Request $request) {
683+ return new Response(
684+ sprintf("Hello %s", $request->get('name'))
685+ );
686+ })
687+ ));
688+
689+ $request = Request::createFromGlobals();
690+
691+ $matcher = new UrlMatcher($routes, new RequestContext());
692+
693+ $dispatcher = new EventDispatcher();
694+ $dispatcher->addSubscriber(new RouterListener($matcher, new RequestStack()));
695+
696+ $argumentValueResolvers = array(
697+ new ArgumentFromAttributeResolver(),
698+ new VariadicArgumentValueResolver(),
699+ new RequestResolver(),
700+ new DefaultArgumentValueResolver(),
701+ );
702+
703+ $controllerResolver = new ControllerResolver();
704+ $argumentResolver = new ArgumentResolver(new ArgumentMetadataFactory(), $argumentValueResolvers);
705+
706+ $kernel = new HttpKernel($dispatcher, $controllerResolver, new RequestStack(), $argumentResolver);
707+
708+ $response = $kernel->handle($request);
709+ $response->send();
710+
711+ $kernel->terminate($request, $response);
619712
620- use Symfony\Component\HttpFoundation\Request;
621- use Symfony\Component\HttpFoundation\RequestStack;
622- use Symfony\Component\HttpFoundation\Response;
623- use Symfony\Component\HttpKernel\HttpKernel;
624- use Symfony\Component\EventDispatcher\EventDispatcher;
625- use Symfony\Component\HttpKernel\Controller\ControllerResolver;
626- use Symfony\Component\HttpKernel\EventListener\RouterListener;
627- use Symfony\Component\Routing\RouteCollection;
628- use Symfony\Component\Routing\Route;
629- use Symfony\Component\Routing\Matcher\UrlMatcher;
630- use Symfony\Component\Routing\RequestContext;
631-
632- $routes = new RouteCollection();
633- $routes->add('hello', new Route('/hello/{name}', array(
634- '_controller' => function (Request $request) {
635- return new Response(
636- sprintf("Hello %s", $request->get('name'))
637- );
638- }
639- )
640- ));
641-
642- $request = Request::createFromGlobals();
643-
644- $matcher = new UrlMatcher($routes, new RequestContext());
645-
646- $dispatcher = new EventDispatcher();
647- $dispatcher->addSubscriber(new RouterListener($matcher, new RequestStack()));
648-
649- $resolver = new ControllerResolver();
650- $kernel = new HttpKernel($dispatcher, $resolver);
651-
652- $response = $kernel->handle($request);
653- $response->send();
654-
655- $kernel->terminate($request, $response);
656713
657714.. _http-kernel-sub-requests :
658715
@@ -716,3 +773,4 @@ look like this::
716773.. _`@ParamConverter` :https://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/converters.html
717774.. _`@Template` :https://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/view.html
718775.. _`EmailSenderListener` :https://github.com/symfony/swiftmailer-bundle/blob/master/EventListener/EmailSenderListener.php
776+ .. _variadic :http://php.net/manual/en/functions.arguments.php