@@ -85,11 +85,22 @@ is really simple and involves creating an
85
85
:doc: `event dispatcher </components/event_dispatcher/introduction >` and a
86
86
:ref: `controller resolver <component-http-kernel-resolve-controller >` (explained
87
87
below). 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
89
98
90
99
use Symfony\Component\HttpFoundation\Request;
91
100
use Symfony\Component\HttpKernel\HttpKernel;
92
101
use Symfony\Component\EventDispatcher\EventDispatcher;
102
+ use Symfony\Component\HttpFoundation\RequestStack;
103
+ use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
93
104
use Symfony\Component\HttpKernel\Controller\ControllerResolver;
94
105
95
106
// create the Request object
@@ -98,10 +109,16 @@ to the events discussed below::
98
109
$dispatcher = new EventDispatcher();
99
110
// ... add some event listeners
100
111
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
+
103
120
// instantiate the kernel
104
- $kernel = new HttpKernel($dispatcher, $resolver );
121
+ $kernel = new HttpKernel($dispatcher, $controllerResolver, new RequestStack(), $argumentResolver );
105
122
106
123
// actually execute the kernel, which turns the request into a response
107
124
// 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
212
229
two methods: ``getController `` and ``getArguments ``. In fact, one default
213
230
implementation already exists, which you can use directly or learn from:
214
231
: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
216
245
217
246
namespace Symfony\Component\HttpKernel\Controller;
218
247
@@ -231,7 +260,7 @@ on the controller resolver. This method is passed the ``Request`` and is respons
231
260
for somehow determining and returning a PHP callable (the controller) based
232
261
on the request's information.
233
262
234
- The second method, :method: `Symfony\\ Component\\ HttpKernel\\ Controller\\ ControllerResolverInterface ::getArguments `,
263
+ The second method, :method: `Symfony\\ Component\\ HttpKernel\\ Controller\\ ArgumentResolverInterface ::getArguments `,
235
264
will be called after another event - ``kernel.controller `` - is dispatched.
236
265
237
266
.. sidebar :: Resolving the Controller in the Symfony Framework
@@ -310,11 +339,11 @@ on the event object that's passed to listeners on this event.
310
339
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
311
340
312
341
Next, ``HttpKernel::handle `` calls
313
- :method: `Symfony\\ Component\\ HttpKernel\\ Controller\\ ControllerResolverInterface ::getArguments `.
342
+ :method: `Symfony\\ Component\\ HttpKernel\\ Controller\\ ArgumentResolverInterface ::getArguments `.
314
343
Remember that the controller returned in ``getController `` is a callable.
315
344
The purpose of ``getArguments `` is to return the array of arguments that
316
345
should 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 `
318
347
is a good example.
319
348
320
349
.. image :: /images/components/http_kernel/07-controller-arguments.png
@@ -326,7 +355,7 @@ of arguments that should be passed when executing that callable.
326
355
.. sidebar :: Getting the Controller Arguments in the Symfony Framework
327
356
328
357
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 `_
330
359
on the callable to return an array of the *names * of each of the arguments.
331
360
It then iterates over each of these arguments and uses the following tricks
332
361
to determine which value should be passed for each argument:
@@ -339,7 +368,18 @@ of arguments that should be passed when executing that callable.
339
368
340
369
b) If the argument in the controller is type-hinted with Symfony's
341
370
: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.
343
383
344
384
.. _component-http-kernel-calling-controller :
345
385
@@ -612,47 +652,64 @@ A full Working Example
612
652
----------------------
613
653
614
654
When 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);
619
712
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);
656
713
657
714
.. _http-kernel-sub-requests :
658
715
@@ -716,3 +773,4 @@ look like this::
716
773
.. _`@ParamConverter` : https://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/converters.html
717
774
.. _`@Template` : https://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/view.html
718
775
.. _`EmailSenderListener` : https://github.com/symfony/swiftmailer-bundle/blob/master/EventListener/EmailSenderListener.php
776
+ .. _variadic : http://php.net/manual/en/functions.arguments.php
0 commit comments