diff --git a/README.md b/README.md index b33ad36..f970f21 100755 --- a/README.md +++ b/README.md @@ -120,6 +120,16 @@ $router = Router::parseConfig($config); $router->matchCurrentRequest(); ``` +## Using a Service Container + +PHPRouter provides a way to work with Containers just by passing it via `PHPRouter\Router` constructor. + +``` +url = $resource; - $this->config = $config; + $this->url = $resource; + $this->config = $config; + + list($controller, $action) = explode('::', $this->config['_controller']); + + $this->controller = $controller; + $this->action = $action; $this->methods = isset($config['methods']) ? (array) $config['methods'] : array(); $this->target = isset($config['target']) ? $config['target'] : null; $this->name = isset($config['name']) ? $config['name'] : null; $this->parameters = isset($config['parameters']) ? $config['parameters'] : array(); } + public function setContainer(ContainerInterface $container) + { + $this->container = $container; + } + public function getUrl() { return $this->url; @@ -187,24 +218,38 @@ public function setParameters(array $parameters) public function dispatch() { - $action = explode('::', $this->config['_controller']); + if (null === $this->getAction()) { + throw new RuntimeException( + sprintf('Could not find an action to controller "%s"', $this->controller) + ); + } if ($this->parametersByName) { $this->parameters = array($this->parameters); } - $this->action = !empty($action[1]) && trim($action[1]) !== '' ? $action[1] : null; + $controller = $this->controller; - if (!is_null($this->action)) { - $instance = new $action[0]; - call_user_func_array(array($instance, $this->action), $this->parameters); + if ($this->container && $this->container->has($controller)) { + $instance = $this->container->get($controller); } else { - $instance = new $action[0]($this->parameters); + $instance = new $controller; + } + + if (method_exists($this, $this->getAction())){ + call_user_func_array( + array($instance, $this->getAction()), + $this->parameters + ); + + return; } + + new $controller($this->parameters); } public function getAction() { - return $this->action; + return '' !== trim($this->action) ? $this->action : null; } } diff --git a/src/Router.php b/src/Router.php index e9bd478..86d1e47 100755 --- a/src/Router.php +++ b/src/Router.php @@ -19,6 +19,7 @@ use Exception; use Fig\Http\Message\RequestMethodInterface; +use Interop\Container\ContainerInterface; /** * Routing class to match request URL's against given routes and map them to a controller action. @@ -45,18 +46,27 @@ class Router private $basePath = ''; /** - * @param RouteCollection $collection + * @var ContainerInterface */ - public function __construct(RouteCollection $collection) + private $container; + + /** + * @param RouteCollection $collection + * @param ContainerInterface $container + */ + public function __construct(RouteCollection $collection, ContainerInterface $container = null) { $this->routes = $collection; + // @todo remove this heavy operation from construct foreach ($this->routes->all() as $route) { $name = $route->getName(); if (null !== $name) { $this->namedRoutes[$name] = $route; } } + + $this->container = $container; } /** diff --git a/tests/src/PHPRouterTest/RouteTest.php b/tests/src/PHPRouterTest/RouteTest.php index e43a18e..2587b0f 100644 --- a/tests/src/PHPRouterTest/RouteTest.php +++ b/tests/src/PHPRouterTest/RouteTest.php @@ -18,10 +18,14 @@ namespace PHPRouterTest\Test; use PHPRouter\Route; +use PHPRouter\Test\SomeController; use PHPUnit_Framework_TestCase; class RouteTest extends PHPUnit_Framework_TestCase { + /** + * @var Route + */ private $routeWithParameters; protected function setUp() @@ -93,4 +97,40 @@ public function testGetAction() { self::assertEquals('page', $this->routeWithParameters->getAction()); } + + public function testShouldGetInstanceFromContainerIfContainerIsProvided() + { + /* @var $container \PHPUnit_Framework_MockObject_MockObject|\Interop\Container\ContainerInterface */ + $container = $this->getMock('Interop\Container\ContainerInterface'); + + $container->expects(self::once()) + ->method('has') + ->with('PHPRouter\Test\SomeController') + ->willReturn(true); + + $container->expects(self::once()) + ->method('get') + ->with('PHPRouter\Test\SomeController') + ->willReturn(new SomeController()); + + $this->routeWithParameters->setContainer($container); + + $this->routeWithParameters->dispatch(); + } + + public function testShouldRaiseAnExceptionIfActionIsNull() + { + $route = new Route( + '/page/:page_id', + array( + '_controller' => 'PHPRouter\Test\SomeController::', + 'methods' => array('GET'), + 'target' => 'thisIsAString', + 'name' => 'page' + ) + ); + + $this->setExpectedException('\RuntimeException'); + $route->dispatch(); + } }