[HttpKernel] added support for controllers as arrays and object with an __invoke method

Controllers can now be any valid PHP callable
This commit is contained in:
Fabien Potencier 2011-04-16 16:26:13 +02:00
parent db8b118e8a
commit c6818d8bf7
3 changed files with 100 additions and 2 deletions

View File

@ -60,7 +60,7 @@ class ControllerResolver implements ControllerResolverInterface
return false;
}
if ($controller instanceof \Closure) {
if (is_array($controller) || method_exists($controller, '__invoke')) {
return $controller;
}
@ -92,15 +92,21 @@ class ControllerResolver implements ControllerResolverInterface
if (is_array($controller)) {
$r = new \ReflectionMethod($controller[0], $controller[1]);
$repr = sprintf('%s::%s()', get_class($controller[0]), $controller[1]);
} elseif (is_object($controller)) {
$r = new \ReflectionObject($controller);
$r = $r->getMethod('__invoke');
$repr = get_class($controller);
} else {
$r = new \ReflectionFunction($controller);
$repr = 'Closure';
$repr = $controller;
}
$arguments = array();
foreach ($r->getParameters() as $param) {
if (array_key_exists($param->getName(), $attributes)) {
$arguments[] = $attributes[$param->getName()];
} elseif ($param->getClass() && $param->getClass()->isInstance($request)) {
$arguments[] = $request;
} elseif ($param->isDefaultValueAvailable()) {
$arguments[] = $param->getDefaultValue();
} else {

View File

@ -36,6 +36,18 @@ class ControllerResolverTest extends \PHPUnit_Framework_TestCase
$controller = $resolver->getController($request);
$this->assertSame($lambda, $controller);
$request->attributes->set('_controller', $this);
$controller = $resolver->getController($request);
$this->assertSame($this, $controller);
$request->attributes->set('_controller', array($this, 'controllerMethod1'));
$controller = $resolver->getController($request);
$this->assertSame(array($this, 'controllerMethod1'), $controller);
$request->attributes->set('_controller', array('Symfony\Tests\Component\HttpKernel\ControllerResolverTest', 'controllerMethod4'));
$controller = $resolver->getController($request);
$this->assertSame(array('Symfony\Tests\Component\HttpKernel\ControllerResolverTest', 'controllerMethod4'), $controller);
$request->attributes->set('_controller', 'foo');
try {
$resolver->getController($request);
@ -98,6 +110,14 @@ class ControllerResolverTest extends \PHPUnit_Framework_TestCase
} catch (\Exception $e) {
$this->assertInstanceOf('\RuntimeException', $e, '->getArguments() throws a \RuntimeException exception if it cannot determine the argument value');
}
$request = Request::create('/');
$controller = array(new self(), 'controllerMethod5');
$this->assertEquals(array($request), $resolver->getArguments($request, $controller), '->getArguments() injects the request');
}
public function __invoke()
{
}
protected function controllerMethod1($foo)
@ -111,4 +131,12 @@ class ControllerResolverTest extends \PHPUnit_Framework_TestCase
protected function controllerMethod3($foo, $bar = null, $foobar)
{
}
static protected function controllerMethod4()
{
}
protected function controllerMethod5(Request $request)
{
}
}

View File

@ -88,6 +88,47 @@ class HttpKernelTest extends \PHPUnit_Framework_TestCase
$kernel->handle(new Request());
}
public function testHandleWhenNoControllerIsAClosure()
{
$response = new Response('foo');
$dispatcher = new EventDispatcher();
$kernel = new HttpKernel($dispatcher, $this->getResolver(function () use ($response) { return $response; }));
$this->assertSame($response, $kernel->handle(new Request()));
}
public function testHandleWhenNoControllerIsAnObjectWithInvoke()
{
$dispatcher = new EventDispatcher();
$kernel = new HttpKernel($dispatcher, $this->getResolver(new Controller()));
$this->assertEquals(new Response('foo'), $kernel->handle(new Request()));
}
public function testHandleWhenNoControllerIsAFunction()
{
$dispatcher = new EventDispatcher();
$kernel = new HttpKernel($dispatcher, $this->getResolver('Symfony\Tests\Component\HttpKernel\controller_func'));
$this->assertEquals(new Response('foo'), $kernel->handle(new Request()));
}
public function testHandleWhenNoControllerIsAnArray()
{
$dispatcher = new EventDispatcher();
$kernel = new HttpKernel($dispatcher, $this->getResolver(array(new Controller(), 'controller')));
$this->assertEquals(new Response('foo'), $kernel->handle(new Request()));
}
public function testHandleWhenNoControllerIsAStaticArray()
{
$dispatcher = new EventDispatcher();
$kernel = new HttpKernel($dispatcher, $this->getResolver(array('Symfony\Tests\Component\HttpKernel\Controller', 'staticcontroller')));
$this->assertEquals(new Response('foo'), $kernel->handle(new Request()));
}
/**
* @expectedException LogicException
*/
@ -140,3 +181,26 @@ class HttpKernelTest extends \PHPUnit_Framework_TestCase
return $resolver;
}
}
class Controller
{
public function __invoke()
{
return new Response('foo');
}
public function controller()
{
return new Response('foo');
}
static public function staticController()
{
return new Response('foo');
}
}
function controller_func()
{
return new Response('foo');
}