Skip to content
This repository was archived by the owner on Dec 6, 2022. It is now read-only.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

```
<?php

$app = new Router($routes, $container);
```

## More information

If you like PHP Router you might also like [AltoRouter](//github.com/dannyvankooten/AltoRouter).
Expand Down
8 changes: 7 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
],
"require": {
"php": "^5.3.0|^7.0",
"fig/http-message-util": "^1.1"
"fig/http-message-util": "^1.1",
"container-interop/container-interop": "^1.1"
},
"require-dev": {
"malukenho/docheader": "^0.1.5",
Expand All @@ -32,5 +33,10 @@
"psr-4": {
"PHPRouter\\": "src/"
}
},
"autoload-dev": {
"classmap": [
"tests/Fixtures/SomeController.php"
]
}
}
67 changes: 56 additions & 11 deletions src/Route.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

use Fig\Http\Message\RequestMethodInterface;
use Exception;
use Interop\Container\ContainerInterface;
use SebastianBergmann\GlobalState\RuntimeException;

class Route
{
Expand All @@ -29,10 +31,14 @@ class Route
private $url;

/**
* Accepted HTTP methods for this route.
* @var string[]
*/
private $methods = array(
private $methods;

/**
* @var string[]
*/
private $httpMethods = array(
RequestMethodInterface::METHOD_GET,
RequestMethodInterface::METHOD_POST,
RequestMethodInterface::METHOD_PUT,
Expand Down Expand Up @@ -75,20 +81,45 @@ class Route
*/
private $config;

/**
* @var ContainerInterface
*/
private $container;

/**
* @var string
*/
private $action;

/**
* @var string
*/
private $controller;

/**
* @param $resource
* @param array $config
*/
public function __construct($resource, array $config)
{
$this->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;
Expand Down Expand Up @@ -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;
}
}
14 changes: 12 additions & 2 deletions src/Router.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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;
}

/**
Expand Down
40 changes: 40 additions & 0 deletions tests/src/PHPRouterTest/RouteTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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();
}
}