Commit 1d3b3183 authored by Fabien Potencier's avatar Fabien Potencier

added converters for request attributes

parent 2ae7fdf4
......@@ -228,6 +228,41 @@ While it's not suggested, you could also do this (note the switched arguments)::
...
});
Route variables converters
~~~~~~~~~~~~~~~~~~~~~~~~~~
Before injecting the route variables into the controller, you can apply some
converters::
$app->get('/user/{id}', function ($id) {
// ...
})->convert('id', function ($id) { return (int) $id; });
This is useful when you want to convert route variables to objects as it
allows to reuse the conversion code across different controllers::
$userProvider = function ($id) {
return new User($id);
};
$app->get('/user/{user}', function (User $user) {
// ...
})->convert('user', $userProvider);
$app->get('/user/{user}/edit', function (User $user) {
// ...
})->convert('user', $userProvider);
The converter callback also receives the ``Request`` as its second argument::
$callback = function ($post, Request $request) {
return new Post($request->attributes->get('slug'));
};
$app->get('/blog/{id}/{slug}', function (Post $post) {
// ...
})->convert('post', $callback);
Requirements
~~~~~~~~~~~~
......
......@@ -17,6 +17,7 @@ use Symfony\Component\HttpKernel\Controller\ControllerResolver;
use Symfony\Component\HttpKernel\Event\KernelEvent;
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Events as HttpKernelEvents;
......@@ -347,6 +348,22 @@ class Application extends \Pimple implements HttpKernelInterface, EventSubscribe
$this['dispatcher']->dispatch(Events::onSilexBefore);
}
/**
* Handles converters.
*
* @param FilterControllerEvent $event A FilterControllerEvent instance
*/
public function onCoreController(FilterControllerEvent $event)
{
$request = $event->getRequest();
$route = $this['routes']->get($request->attributes->get('_route'));
if ($route && $converters = $route->getOption('_converters')) {
foreach ($converters as $name => $callback) {
$request->attributes->set($name, call_user_func($callback, $request->attributes->get($name, null), $request));
}
}
}
/**
* Handles string responses.
*
......@@ -396,6 +413,7 @@ class Application extends \Pimple implements HttpKernelInterface, EventSubscribe
return array(
HttpKernelEvents::onCoreRequest,
HttpKernelEvents::onCoreController,
HttpKernelEvents::onCoreResponse,
HttpKernelEvents::onCoreException,
);
......
......@@ -95,6 +95,21 @@ class Controller
return $this;
}
/**
* Sets a converter for a route variable.
*
* @param string $variable The variable name
* @param mixed $callback A PHP callback that converts the original value
*/
public function convert($variable, $callback)
{
$converters = $this->route->getOption('_converters');
$converters[$variable] = $callback;
$this->route->setOption('_converters', $converters);
return $this;
}
/**
* Freezes the controller.
*
......
......@@ -85,6 +85,25 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(2, count($routes->all()));
}
public function testOnCoreController()
{
$app = new Application();
$app->get('/foo/{foo}', function (\ArrayObject $foo) {
return $foo['foo'];
})->convert('foo', function ($foo) { return new \ArrayObject(array('foo' => $foo)); });
$response = $app->handle(Request::create('/foo/bar'));
$this->assertEquals('bar', $response->getContent());
$app->get('/foo/{foo}/{bar}', function (\ArrayObject $foo) {
return $foo['foo'];
})->convert('foo', function ($foo, Request $request) { return new \ArrayObject(array('foo' => $foo.$request->attributes->get('bar'))); });
$response = $app->handle(Request::create('/foo/foo/bar'));
$this->assertEquals('foobar', $response->getContent());
}
/**
* @dataProvider escapeProvider
*/
......
......@@ -60,6 +60,15 @@ class ControllerTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(array('bar' => 'foo'), $controller->getRoute()->getDefaults());
}
public function testConvert()
{
$controller = new Controller(new Route('/foo/{bar}'));
$ret = $controller->convert('bar', $func = function ($bar) { return $bar; });
$this->assertSame($ret, $controller);
$this->assertEquals(array('bar' => $func), $controller->getRoute()->getOption('_converters'));
}
/**
* @dataProvider provideRouteAndExpectedRouteName
*/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment