Skip to content

Commit

Permalink
Documented the ArgumentResolver along the ControllerResolver
Browse files Browse the repository at this point in the history
  • Loading branch information
Iltar van der Berg committed Apr 1, 2016
1 parent d7724dd commit 678c705
Showing 1 changed file with 52 additions and 19 deletions.
71 changes: 52 additions & 19 deletions create_framework/http_kernel_controller_resolver.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,20 @@ 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

.. 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.

.. code-block:: php
namespace Symfony\Component\HttpKernel\Controller;
Expand All @@ -58,6 +68,12 @@ a Request object. All controller resolvers implement the following interface::
function getArguments(Request $request, $controller);
}
// ...
interface ArgumentResolverInterface
{
function getArguments(Request $request, $controller);
}
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,
Expand All @@ -74,10 +90,14 @@ resolver from HttpKernel::

use Symfony\Component\HttpKernel;

$resolver = new HttpKernel\Controller\ControllerResolver();
$valueResolvers = [/* array of ArgumentValueResolverInterface implemetations */];
$argumentMetadataFactory = new Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory();

$controllerResolver = new HttpKernel\Controller\ControllerResolver();
$argumentResolver = new HttpKernel\Controller\ArgumentResolver($argumentMetadataFactory, $valueResolvers);

$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);

Expand Down Expand Up @@ -140,20 +160,19 @@ 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 </cookbook/controller/service>`; 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 </cookbook/controller/service>`;
and ``getArguments()`` provides an extension point to alter or enhance
the resolving of arguments.

Let's conclude with the new version of our framework::

// example.com/web/front.php
require_once __DIR__.'/../vendor/autoload.php';

use Symfony\Component\HttpKernel\Controller\ArgumentValueResolver as ArgumentValueResolver;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing;
Expand All @@ -174,13 +193,27 @@ 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();

$valueResolvers = [
new ArgumentValueResolver\ArgumentFromAttributeResolver(),
new ArgumentValueResolver\VariadicArgumentValueResolver(),
new ArgumentValueResolver\RequestResolver(),
new ArgumentValueResolver\DefaultArgumentValueResolver(),
];

$argumentMetadataFactory = new Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory();

$controllerResolver = new HttpKernel\Controller\ControllerResolver();
$argumentResolver = new HttpKernel\Controller\ArgumentResolver($argumentMetadataFactory, $valueResolvers);

$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) {
Expand All @@ -192,7 +225,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 60 lines of code.

.. _`reflection`: http://php.net/reflection
.. _`FrameworkExtraBundle`: http://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/converters.html
Expand Down

0 comments on commit 678c705

Please sign in to comment.