Development

- Made easier to extend.
- Added IRoute class.
- Changed namespace for Route classes.
- Moved find-url related stuff to Route classes itself.
- Added more tests for finding urls.
- Added support for custom names on RouteController and RouteResource.
- Removed depricated methods.
- Updated documentation.
- Updated demo-project to reflect changes.
- Other small bugfixes and improvements.
This commit is contained in:
Simon Sessingø
2016-11-21 01:50:28 +01:00
parent df3acb6605
commit 8370d3d94e
26 changed files with 757 additions and 474 deletions
+78 -24
View File
@@ -158,11 +158,11 @@ namespace Demo\Handlers;
use Pecee\Handlers\IExceptionHandler; use Pecee\Handlers\IExceptionHandler;
use Pecee\Http\Request; use Pecee\Http\Request;
use Pecee\SimpleRouter\Exceptions\NotFoundHttpException; use Pecee\SimpleRouter\Exceptions\NotFoundHttpException;
use Pecee\SimpleRouter\RouterEntry; use Pecee\SimpleRouter\Route\ILoadableRoute;
class CustomExceptionHandler implements IExceptionHandler class CustomExceptionHandler implements IExceptionHandler
{ {
public function handleError(Request $request, RouterEntry &$route = null, \Exception $error) public function handleError(Request $request, ILoadableRoute &$route = null, \Exception $error)
{ {
/* You can use the exception handler to format errors depending on the request and type. */ /* You can use the exception handler to format errors depending on the request and type. */
@@ -214,18 +214,19 @@ Route::group(['domain' => '{account}.myapp.com'], function () {
The prefix group array attribute may be used to prefix each route in the group with a given URI. For example, you may want to prefix all route URIs within the group with admin: The prefix group array attribute may be used to prefix each route in the group with a given URI. For example, you may want to prefix all route URIs within the group with admin:
### Doing it the object oriented (hardcore) way ### Adding routes manually (with no helper)
The ```SimpleRouter``` class referenced in the previous example, is just a simple helper class that knows how to communicate with the ```RouterBase``` class. The ```SimpleRouter``` class referenced in the previous example, is just a simple helper class that knows how to communicate with the ```Router``` class.
If you are up for a challenge, want the full control or simply just want to create your own ```Router``` helper class, this example is for you. If you are up for a challenge, want the full control or simply just want to create your own ```Router``` helper class, this example is for you.
```php ```php
use \Pecee\SimpleRouter\RouterBase; use \Pecee\SimpleRouter\Router;
use \Pecee\SimpleRouter\RouterRoute; use \Pecee\SimpleRouter\Route\RouteUrl;
$router = RouterBase::getInstance(); /* Grap the router instance */
$router = Router::getInstance();
$route = new RouterRoute('/answer/1', function() { $route = new RouteUrl('/answer/1', function() {
die('this callback will match /answer/1'); die('this callback will match /answer/1');
@@ -239,9 +240,11 @@ $route->setPrefix('v1');
$router->addRoute($route); $router->addRoute($route);
``` ```
### Extending
This is a simple example of an integration into a framework. This is a simple example of an integration into a framework.
The framework has it's own ```Router``` class which inherits from the ```SimpleRouter``` class. This allows the framework to add custom functionality. The framework has it's own ```Router``` class which inherits from the ```SimpleRouter``` class. This allows the framework to add custom functionality like loading a custom `routes.php` file or add debugging information etc.
```php ```php
namespace Demo; namespace Demo;
@@ -330,22 +333,73 @@ function input() {
## Getting urls ## Getting urls
**In ```routes.php``` we have added this route:** By default all controller and resource routes will use a simplified version of their url as name.
**Get routes using custom name (single route)**
```php ```php
SimpleRouter::get('/item/{id}', 'myController@show', ['as' => 'item']); SimpleRouter::get('/product-view/{id}', 'ProductsController@show', ['as' => 'product']);
url('product', ['id' => 22], ['category' => 'shoes']);
# output
# /product-view/22/?category=shoes
``` ```
**In the template we then call:** **Getting the url using the name (controller route)**
```php ```php
url('item', ['id' => 22], ['category' => 'shoes']); SimpleRouter::controller('/images', 'ImagesController', ['as' => 'picture']);
url('picture@getView', null, ['category' => 'shoes']);
url('picture', 'getView', ['category' => 'shoes']);
# output
# /images/view/?category=shows
# /images/view/?category=shows
``` ```
**Result url is:** **Getting the url using class**
```php ```php
/item/22/?category=shoes SimpleRouter::get('/product-view/{id}', 'ProductsController@show', ['as' => 'product']);
SimpleRouter::controller('/images', 'ImagesController');
url('ProductsController@show', ['id' => 22], ['category' => 'shoes']);
url('ImagesController@getImage', null, ['id' => 22]);
# output
# /product-view/22/?category=shoes
# /images/image/?category=shows
```
**Using custom names for methods on a controller/resource route**
```php
SimpleRouter::controller('gadgets', 'GadgetsController', ['names' => ['getIphoneInfo' => 'iphone']]);
url('gadgets.iphone');
# output
# /gadgets/iphoneinfo/
```
**Getting REST/resource controller urls**
```php
SimpleRouter::resource('/phones', 'PhonesController');
url('phones');
url('phones.index');
url('phones.create');
url('phones.edit');
// etc..
# output
# /phones/
# /phones/create/
# /phones/edit/
``` ```
## Custom CSRF verifier ## Custom CSRF verifier
@@ -379,13 +433,13 @@ SimpleRouter::csrfVerifier(new \Demo\Middleware\CsrfVerifier());
Sometimes it can be necessary to keep urls stored in the database, file or similar. In this example, we want the url ```/my-cat-is-beatiful``` to load the route ```/article/view/1``` which the router knows, because it's defined in the ```routes.php``` file. Sometimes it can be necessary to keep urls stored in the database, file or similar. In this example, we want the url ```/my-cat-is-beatiful``` to load the route ```/article/view/1``` which the router knows, because it's defined in the ```routes.php``` file.
To interfere with the router, we create a class that inherits from ```RouterBootManager```. This class will be loaded before any other rules in ```routes.php``` and allow us to "change" the current route, if any of our criteria are fulfilled (like coming from the url ```/my-cat-is-beatiful```). To interfere with the router, we create a class that implements the ```IRouterBootManager``` interface. This class will be loaded before any other rules in ```routes.php``` and allow us to "change" the current route, if any of our criteria are fulfilled (like coming from the url ```/my-cat-is-beatiful```).
```php ```php
use Pecee\Http\Request; use Pecee\Http\Request;
use Pecee\SimpleRouter\RouterBootManager; use Pecee\SimpleRouter\IRouterBootManager;
class CustomRouterRules extends RouterBootManager { class CustomRouterRules implement IRouterBootManager {
public function boot(Request $request) { public function boot(Request $request) {
@@ -421,7 +475,7 @@ The last thing we need to do, is to add our custom boot-manager to the ```routes
## Easily overwrite route about to be loaded ## Easily overwrite route about to be loaded
Sometimes it can be useful to manipulate the route about to be loaded. Sometimes it can be useful to manipulate the route about to be loaded.
simple-php-router allows you to easily change the route about to be executed. simple-php-router allows you to easily change the route about to be executed.
All information about the current route is stored in the ```\Pecee\SimpleRouter\RouterBase``` instance's `loadedRoute` property. All information about the current route is stored in the ```\Pecee\SimpleRouter\Router``` instance's `loadedRoute` property.
For easy access you can use the shortcut method `\Pecee\SimpleRouter\SimpleRouter::router()`. For easy access you can use the shortcut method `\Pecee\SimpleRouter\SimpleRouter::router()`.
@@ -442,7 +496,7 @@ $route->setMethod('hello');
### Examples ### Examples
It's only possible to change the route BEFORE the route has initially been loaded. If you want to redirect to another route, we highly recommend that you It's only possible to change the route BEFORE the route has initially been loaded. If you want to redirect to another route, we highly recommend that you
modify the `RouterEntry` object from a `Middleware` or `ExceptionHandler`, like the examples below. modify the `IRoute` object from a `Middleware` or `ExceptionHandler`, like the examples below.
#### Rewriting to new route #### Rewriting to new route
@@ -456,11 +510,11 @@ namespace Demo\Middlewares;
use Pecee\Http\Middleware\IMiddleware; use Pecee\Http\Middleware\IMiddleware;
use Pecee\Http\Request; use Pecee\Http\Request;
use Pecee\SimpleRouter\RouterEntry; use Pecee\SimpleRouter\Route\ILoadableRoute;
class CustomMiddleware implements Middleware { class CustomMiddleware implements Middleware {
public function handle(Request $request, RouterEntry &$route) { public function handle(Request $request, ILoadableRoute &$route) {
$request->setUri(url('home')); $request->setUri(url('home'));
@@ -484,11 +538,11 @@ namespace Demo\Middlewares;
use Pecee\Http\Middleware\IMiddleware; use Pecee\Http\Middleware\IMiddleware;
use Pecee\Http\Request; use Pecee\Http\Request;
use Pecee\SimpleRouter\RouterEntry; use Pecee\SimpleRouter\Route\ILoadableRoute;
class CustomMiddleware implements Middleware { class CustomMiddleware implements Middleware {
public function handle(Request $request, RouterEntry &$route) { public function handle(Request $request, ILoadableRoute &$route) {
$route->callback('DefaultController@home'); $route->callback('DefaultController@home');
@@ -4,11 +4,11 @@ namespace Demo\Handlers;
use Pecee\Handlers\IExceptionHandler; use Pecee\Handlers\IExceptionHandler;
use Pecee\Http\Request; use Pecee\Http\Request;
use Pecee\SimpleRouter\Exceptions\NotFoundHttpException; use Pecee\SimpleRouter\Exceptions\NotFoundHttpException;
use Pecee\SimpleRouter\RouterEntry; use Pecee\SimpleRouter\Route\ILoadableRoute;
class CustomExceptionHandler implements IExceptionHandler class CustomExceptionHandler implements IExceptionHandler
{ {
public function handleError(Request $request, RouterEntry &$route = null, \Exception $error) public function handleError(Request $request, ILoadableRoute &$route = null, \Exception $error)
{ {
/* You can use the exception handler to format errors depending on the request and type. */ /* You can use the exception handler to format errors depending on the request and type. */
@@ -3,11 +3,11 @@ namespace Demo\Middlewares;
use Pecee\Http\Middleware\IMiddleware; use Pecee\Http\Middleware\IMiddleware;
use Pecee\Http\Request; use Pecee\Http\Request;
use Pecee\SimpleRouter\RouterEntry; use Pecee\SimpleRouter\Route\ILoadableRoute;
class ApiVerification implements IMiddleware class ApiVerification implements IMiddleware
{ {
public function handle(Request $request, RouterEntry &$route) public function handle(Request $request, ILoadableRoute &$route)
{ {
// Do authentication // Do authentication
$request->authenticated = true; $request->authenticated = true;
+3 -3
View File
@@ -2,16 +2,16 @@
namespace Pecee\Handlers; namespace Pecee\Handlers;
use Pecee\Http\Request; use Pecee\Http\Request;
use Pecee\SimpleRouter\RouterEntry; use Pecee\SimpleRouter\Route\ILoadableRoute;
interface IExceptionHandler interface IExceptionHandler
{ {
/** /**
* @param Request $request * @param Request $request
* @param RouterEntry|null $route * @param ILoadableRoute $route
* @param \Exception $error * @param \Exception $error
* @return Request|null * @return Request|null
*/ */
public function handleError(Request $request, RouterEntry &$route = null, \Exception $error); public function handleError(Request $request, ILoadableRoute &$route = null, \Exception $error);
} }
@@ -4,7 +4,7 @@ namespace Pecee\Http\Middleware;
use Pecee\CsrfToken; use Pecee\CsrfToken;
use Pecee\Exceptions\TokenMismatchException; use Pecee\Exceptions\TokenMismatchException;
use Pecee\Http\Request; use Pecee\Http\Request;
use Pecee\SimpleRouter\RouterEntry; use Pecee\SimpleRouter\Route\ILoadableRoute;
class BaseCsrfVerifier implements IMiddleware class BaseCsrfVerifier implements IMiddleware
{ {
@@ -51,7 +51,7 @@ class BaseCsrfVerifier implements IMiddleware
return false; return false;
} }
public function handle(Request $request, RouterEntry &$route = null) public function handle(Request $request, ILoadableRoute &$route = null)
{ {
if ($request->getMethod() !== 'get' && !$this->skip($request)) { if ($request->getMethod() !== 'get' && !$this->skip($request)) {
+3 -3
View File
@@ -2,15 +2,15 @@
namespace Pecee\Http\Middleware; namespace Pecee\Http\Middleware;
use Pecee\Http\Request; use Pecee\Http\Request;
use Pecee\SimpleRouter\RouterEntry; use Pecee\SimpleRouter\Route\ILoadableRoute;
interface IMiddleware interface IMiddleware
{ {
/** /**
* @param Request $request * @param Request $request
* @param RouterEntry $route * @param ILoadableRoute $route
* @return Request|null * @return Request|null
*/ */
public function handle(Request $request, RouterEntry &$route); public function handle(Request $request, ILoadableRoute &$route);
} }
@@ -1,9 +0,0 @@
<?php
namespace Pecee\SimpleRouter;
interface ILoadableRoute
{
public function getUrl();
public function setUrl($url);
}
@@ -0,0 +1,9 @@
<?php
namespace Pecee\SimpleRouter;
use Pecee\Http\Request;
interface IRouterBootManager
{
public function boot(Request $request);
}
-151
View File
@@ -1,151 +0,0 @@
<?php
namespace Pecee\SimpleRouter;
abstract class LoadableRoute extends RouterEntry implements ILoadableRoute
{
const PARAMETERS_REGEX_MATCH = '%s([\w\-\_]*?)\%s{0,1}%s';
const PARAMETER_MODIFIERS = '{}';
const PARAMETER_OPTIONAL_SYMBOL = '?';
protected $url;
protected $names = [];
public function getUrl()
{
return $this->url;
}
/**
* Set url
*
* @param string $url
* @return static
*/
public function setUrl($url)
{
$this->url = ($url === '/') ? '/' : '/' . trim($url, '/') . '/';
$regex = sprintf(static::PARAMETERS_REGEX_MATCH, static::PARAMETER_MODIFIERS[0], static::PARAMETER_OPTIONAL_SYMBOL, static::PARAMETER_MODIFIERS[1]);
if (preg_match_all('/' . $regex . '/is', $this->url, $matches)) {
foreach ($matches[1] as $key) {
$this->parameters[$key] = null;
}
}
return $this;
}
/**
* Returns the provided name of the router (first if multiple).
* Alias for LoadableRoute::getName().
*
* @see LoadableRoute::getName()
* @return string|array
*/
public function getAlias()
{
return $this->getName();
}
/**
* Returns the provided name for the router (first if multiple).
* @return string
*/
public function getName()
{
return $this->names[0];
}
/**
* Get route names
* @return array
*/
public function getNames()
{
return $this->names;
}
/**
* Check if route has given name.
* Alias for LoadableRoute::hasName();
*
* @see LoadableRoute::hasName()
* @param $name
*/
public function hasAlias($name)
{
$this->hasName($name);
}
/**
* Check if route has given name.
*
* @param string $name
* @return bool
*/
public function hasName($name)
{
return (in_array($name, $this->names, false) !== false);
}
/**
* Sets the router name, which makes it easier to obtain the url or router at a later point.
* Alias for LoadableRoute::setName().
*
* @see LoadableRoute::setName()
* @param string|array $name
* @return static
*/
public function setAlias($name)
{
return $this->setName($name);
}
/**
* Sets the router name, which makes it easier to obtain the url or router at a later point.
*
* @param string $name
* @return static $this
*/
public function setName($name)
{
array_push($this->names, $name);
return $this;
}
/**
* Set multiple names for the route
*
* @param array $names
* @return static $this
*/
public function setNames(array $names)
{
$this->names = $names;
return $this;
}
/**
* Merge with information from another route.
*
* @param array $values
* @return static
*/
public function setSettings(array $values)
{
if (isset($values['as'])) {
$this->setNames((array)$values['as']);
}
if (isset($values['prefix'])) {
$this->setUrl($values['prefix'] . $this->getUrl());
}
parent::setSettings($values);
return $this;
}
}
@@ -1,7 +1,7 @@
<?php <?php
namespace Pecee\SimpleRouter; namespace Pecee\SimpleRouter\Route;
interface IControllerRoute interface IControllerRoute extends IRoute
{ {
public function getController(); public function getController();
@@ -0,0 +1,21 @@
<?php
namespace Pecee\SimpleRouter\Route;
use Pecee\Http\Request;
interface IGroupRoute extends IRoute
{
public function matchDomain(Request $request);
public function setExceptionHandlers(array $handlers);
public function getExceptionHandlers();
public function getDomains();
public function setDomains(array $domains);
public function setPrefix($prefix);
public function getPrefix();
}
@@ -0,0 +1,29 @@
<?php
namespace Pecee\SimpleRouter\Route;
use Pecee\Http\Request;
interface ILoadableRoute extends IRoute
{
public function findUrl($method = null, $parameters = null, $name = null);
public function loadMiddleware(Request $request, ILoadableRoute &$route);
public function getUrl();
public function setUrl($url);
public function getName();
public function hasName($name);
public function setName($name);
public function getMiddlewares();
public function setMiddleware($middleware);
public function setMiddlewares(array $middlewares);
}
@@ -1,25 +1,27 @@
<?php <?php
namespace Pecee\SimpleRouter; namespace Pecee\SimpleRouter\Route;
use Pecee\Http\Request; use Pecee\Http\Request;
interface IRoute interface IRoute
{ {
public function renderRoute(Request $request);
public function loadMiddleware(Request $request, LoadableRoute &$route);
public function getIdentifier(); public function getIdentifier();
public function setRequestMethods(array $methods); public function setRequestMethods(array $methods);
public function getRequestMethods(); public function getRequestMethods();
/**
* @return IRoute
*/
public function getParent(); public function getParent();
/**
* @return IGroupRoute
*/
public function getGroup(); public function getGroup();
public function setGroup(RouterGroup $group); public function setGroup(IGroupRoute $group);
public function setParent(IRoute $parent); public function setParent(IRoute $parent);
@@ -33,32 +35,30 @@ interface IRoute
public function setMethod($method); public function setMethod($method);
public function setMiddleware($middleware);
public function setMiddlewares(array $middlewares);
public function setNamespace($namespace); public function setNamespace($namespace);
public function setDefaultNamespace($namespace); public function setDefaultNamespace($namespace);
public function getDefaultNamespace(); public function getDefaultNamespace();
public function getMiddlewares();
public function getNamespace(); public function getNamespace();
public function getParameters();
public function setParameters($parameters);
public function setWhere(array $options);
public function setMatch($regex);
public function toArray(); public function toArray();
public function setSettings(array $settings); public function setSettings(array $settings, $merge = false);
public function matchRoute(Request $request); public function matchRoute(Request $request);
public function setMatch($regex);
public function setWhere(array $options);
public function getWhere();
public function getParameters();
public function setParameters(array $parameters);
public function renderRoute(Request $request);
} }
@@ -0,0 +1,214 @@
<?php
namespace Pecee\SimpleRouter\Route;
use Pecee\Http\Middleware\IMiddleware;
use Pecee\Http\Request;
use Pecee\SimpleRouter\Exceptions\HttpException;
abstract class LoadableRoute extends Route implements ILoadableRoute
{
const PARAMETERS_REGEX_MATCH = '%s([\w\-\_]*?)\%s{0,1}%s';
protected $url;
protected $name;
protected $middlewares = [];
public function loadMiddleware(Request $request, ILoadableRoute &$route)
{
if (count($this->getMiddlewares()) > 0) {
foreach ($this->getMiddlewares() as $middleware) {
$middleware = $this->loadClass($middleware);
if (!($middleware instanceof IMiddleware)) {
throw new HttpException($middleware . ' must be instance of Middleware');
}
$middleware->handle($request, $route);
}
}
}
/**
* Set url
*
* @param string $url
* @return static
*/
public function setUrl($url)
{
$this->url = ($url === '/') ? '/' : '/' . trim($url, '/') . '/';
$regex = sprintf(static::PARAMETERS_REGEX_MATCH, $this->paramModifiers[0], $this->paramOptionalSymbol, $this->paramModifiers[1]);
if (preg_match_all('/' . $regex . '/is', $this->url, $matches)) {
foreach ($matches[1] as $key) {
$this->parameters[$key] = null;
}
}
return $this;
}
public function getUrl()
{
return $this->url;
}
public function findUrl($method = null, $parameters = null, $name = null)
{
$url = '';
$parameters = (array)$parameters;
if ($this->getGroup() !== null && count($this->getGroup()->getDomains()) > 0) {
$url .= '//' . $this->getGroup()->getDomains()[0];
}
$url .= $this->getUrl();
$params = array_merge($this->getParameters(), $parameters);
/* Url that contains parameters that aren't recognized */
$unknownParams = [];
/* Create the param string - {} */
$param1 = $this->paramModifiers[0] . '%s' . $this->paramModifiers[1];
/* Create the param string with the optional symbol - {?} */
$param2 = $this->paramModifiers[0] . '%s' . $this->paramOptionalSymbol . $this->paramModifiers[1];
/* Let's parse the values of any {} parameter in the url */
foreach ($params as $param => $value) {
$value = (isset($parameters[$param])) ? $parameters[$param] : $value;
if (stripos($url, $param1) !== false || stripos($url, $param) !== false) {
$url = str_ireplace([sprintf($param1, $param), sprintf($param2, $param)], $value, $url);
} else {
$unknownParams[$param] = $value;
}
}
$url .= '/' . join('/', $unknownParams);
return rtrim($url, '/') . '/';
}
/**
* Returns the provided name for the router (first if multiple).
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Check if route has given name.
*
* @param string $name
* @return bool
*/
public function hasName($name)
{
return (strtolower($this->name) === strtolower($name));
}
/**
* Sets the router name, which makes it easier to obtain the url or router at a later point.
* Alias for LoadableRoute::setName().
*
* @see LoadableRoute::setName()
* @param string|array $name
* @return static
*/
public function name($name)
{
return $this->setName($name);
}
/**
* Sets the router name, which makes it easier to obtain the url or router at a later point.
*
* @param string $name
* @return static $this
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Export route settings to array so they can be merged with another route.
*
* @return array
*/
public function toArray()
{
$values = [];
if (count($this->middlewares) > 0) {
$values['middleware'] = $this->middlewares;
}
return array_merge(parent::toArray(), $values);
}
/**
* Merge with information from another route.
*
* @param array $values
* @param bool $merge
* @return static
*/
public function setSettings(array $values, $merge = false)
{
if (isset($values['as'])) {
if ($this->name !== null && $merge !== false) {
$this->setName($values['as'] . '.' . $this->name);
} else {
$this->setName($values['as']);
}
}
if (isset($values['prefix'])) {
$this->setUrl($values['prefix'] . $this->getUrl());
}
// Push middleware if multiple
if (isset($values['middleware'])) {
$this->setMiddlewares(array_merge((array)$values['middleware'], $this->middlewares));
}
parent::setSettings($values, $merge);
return $this;
}
/**
* @param string $middleware
* @return static
*/
public function setMiddleware($middleware)
{
$this->middlewares[] = $middleware;
return $this;
}
public function setMiddlewares(array $middlewares)
{
$this->middlewares = $middlewares;
return $this;
}
/**
* @return string|array
*/
public function getMiddlewares()
{
return $this->middlewares;
}
}
@@ -1,12 +1,11 @@
<?php <?php
namespace Pecee\SimpleRouter; namespace Pecee\SimpleRouter\Route;
use Pecee\Http\Middleware\IMiddleware;
use Pecee\Http\Request; use Pecee\Http\Request;
use Pecee\SimpleRouter\Exceptions\HttpException; use Pecee\SimpleRouter\Exceptions\HttpException;
use Pecee\SimpleRouter\Exceptions\NotFoundHttpException; use Pecee\SimpleRouter\Exceptions\NotFoundHttpException;
abstract class RouterEntry implements IRoute abstract class Route implements IRoute
{ {
const REQUEST_TYPE_GET = 'get'; const REQUEST_TYPE_GET = 'get';
const REQUEST_TYPE_POST = 'post'; const REQUEST_TYPE_POST = 'post';
@@ -24,6 +23,8 @@ abstract class RouterEntry implements IRoute
self::REQUEST_TYPE_DELETE, self::REQUEST_TYPE_DELETE,
]; ];
protected $paramModifiers = '{}';
protected $paramOptionalSymbol = '?';
protected $group; protected $group;
protected $parent; protected $parent;
protected $callback; protected $callback;
@@ -35,15 +36,37 @@ abstract class RouterEntry implements IRoute
protected $requestMethods = []; protected $requestMethods = [];
protected $where = []; protected $where = [];
protected $parameters = []; protected $parameters = [];
protected $middlewares = [];
protected function loadClass($name) public function renderRoute(Request $request)
{ {
if (!class_exists($name)) { if ($this->getCallback() !== null && is_callable($this->getCallback())) {
throw new HttpException(sprintf('Class %s does not exist', $name), 500);
/* When the callback is a function */
call_user_func_array($this->getCallback(), $this->getParameters());
} else {
/* When the callback is a method */
$controller = explode('@', $this->getCallback());
$className = $this->getNamespace() . '\\' . $controller[0];
$class = $this->loadClass($className);
$method = $controller[1];
if (!method_exists($class, $method)) {
throw new NotFoundHttpException(sprintf('Method %s does not exist in class %s', $method, $className), 404);
} }
return new $name(); $parameters = array_filter($this->getParameters(), function ($var) {
return ($var !== null);
});
call_user_func_array([$class, $method], $parameters);
return $class;
}
return null;
} }
protected function parseParameters($route, $url, $parameterRegex = '[\w]+') protected function parseParameters($route, $url, $parameterRegex = '[\w]+')
@@ -125,51 +148,13 @@ abstract class RouterEntry implements IRoute
return null; return null;
} }
public function loadMiddleware(Request $request, LoadableRoute &$route) protected function loadClass($name)
{ {
if (count($this->getMiddlewares()) > 0) { if (!class_exists($name)) {
foreach ($this->getMiddlewares() as $middleware) { throw new HttpException(sprintf('Class %s does not exist', $name), 500);
$middleware = $this->loadClass($middleware);
if (!($middleware instanceof IMiddleware)) {
throw new HttpException($middleware . ' must be instance of Middleware');
} }
$middleware->handle($request, $route); return new $name();
}
}
}
public function renderRoute(Request $request)
{
if ($this->getCallback() !== null && is_callable($this->getCallback())) {
/* When the callback is a function */
call_user_func_array($this->getCallback(), $this->getParameters());
} else {
/* When the callback is a method */
$controller = explode('@', $this->getCallback());
$className = $this->getNamespace() . '\\' . $controller[0];
$class = $this->loadClass($className);
$method = $controller[1];
if (!method_exists($class, $method)) {
throw new NotFoundHttpException(sprintf('Method %s does not exist in class %s', $method, $className), 404);
}
$parameters = array_filter($this->getParameters(), function ($var) {
return ($var !== null);
});
call_user_func_array([$class, $method], $parameters);
return $class;
}
return null;
} }
/** /**
@@ -221,7 +206,7 @@ abstract class RouterEntry implements IRoute
/** /**
* Get the group for the route. * Get the group for the route.
* *
* @return RouterGroup|null * @return IGroupRoute|null
*/ */
public function getGroup() public function getGroup()
{ {
@@ -231,11 +216,14 @@ abstract class RouterEntry implements IRoute
/** /**
* Set group * Set group
* *
* @param RouterGroup $group * @param IGroupRoute $group
* @return static $this
*/ */
public function setGroup(RouterGroup $group) public function setGroup(IGroupRoute $group)
{ {
$this->group = $group; $this->group = $group;
return $this;
} }
/** /**
@@ -306,24 +294,6 @@ abstract class RouterEntry implements IRoute
return $this; return $this;
} }
/**
* @param string $middleware
* @return static
*/
public function setMiddleware($middleware)
{
$this->middlewares[] = $middleware;
return $this;
}
public function setMiddlewares(array $middlewares)
{
$this->middlewares = $middlewares;
return $this;
}
/** /**
* @param string $namespace * @param string $namespace
* @return static $this * @return static $this
@@ -351,14 +321,6 @@ abstract class RouterEntry implements IRoute
return $this->defaultNamespace; return $this->defaultNamespace;
} }
/**
* @return string|array
*/
public function getMiddlewares()
{
return $this->middlewares;
}
/** /**
* @return string * @return string
*/ */
@@ -367,38 +329,6 @@ abstract class RouterEntry implements IRoute
return ($this->namespace === null) ? $this->defaultNamespace : $this->namespace; return ($this->namespace === null) ? $this->defaultNamespace : $this->namespace;
} }
/**
* @return array
*/
public function getParameters()
{
return $this->parameters;
}
/**
* @param mixed $parameters
* @return static
*/
public function setParameters($parameters)
{
$this->parameters = $parameters;
return $this;
}
/**
* Add regular expression parameter match
*
* @param array $options
* @return static
*/
public function setWhere(array $options)
{
$this->where = $options;
return $this;
}
/** /**
* Add regular expression match for the entire route. * Add regular expression match for the entire route.
* *
@@ -425,18 +355,14 @@ abstract class RouterEntry implements IRoute
$values['namespace'] = $this->namespace; $values['namespace'] = $this->namespace;
} }
if (count($this->middlewares) > 0) { if (count($this->requestMethods) > 0) {
$values['middleware'] = $this->middlewares; $values['method'] = $this->requestMethods;
} }
if (count($this->where) > 0) { if (count($this->where) > 0) {
$values['where'] = $this->where; $values['where'] = $this->where;
} }
if (count($this->requestMethods) > 0) {
$values['method'] = $this->requestMethods;
}
if (count($this->parameters) > 0) { if (count($this->parameters) > 0) {
$values['parameters'] = $this->parameters; $values['parameters'] = $this->parameters;
} }
@@ -448,19 +374,15 @@ abstract class RouterEntry implements IRoute
* Merge with information from another route. * Merge with information from another route.
* *
* @param array $values * @param array $values
* @param bool $merge
* @return static $this * @return static $this
*/ */
public function setSettings(array $values) public function setSettings(array $values, $merge = false)
{ {
if (isset($values['namespace']) && $this->namespace === null) { if (isset($values['namespace']) && $this->namespace === null) {
$this->setNamespace($values['namespace']); $this->setNamespace($values['namespace']);
} }
// Push middleware if multiple
if (isset($values['middleware'])) {
$this->setMiddlewares(array_merge((array)$values['middleware'], $this->middlewares));
}
if (isset($values['method'])) { if (isset($values['method'])) {
$this->setRequestMethods(array_merge($this->requestMethods, (array)$values['method'])); $this->setRequestMethods(array_merge($this->requestMethods, (array)$values['method']));
} }
@@ -476,4 +398,60 @@ abstract class RouterEntry implements IRoute
return $this; return $this;
} }
/**
* Get parameter names.
*
* @return array
*/
public function getWhere()
{
return $this->where;
}
/**
* Set parameter names.
*
* @param array $options
* @return static
*/
public function setWhere(array $options)
{
$this->where = $options;
return $this;
}
/**
* Add regular expression parameter match.
* Alias for LoadableRoute::where()
*
* @see LoadableRoute::where()
* @param array $options
* @return static
*/
public function where(array $options) {
return $this->where($options);
}
/**
* Get parameters
*
* @return array
*/
public function getParameters()
{
return $this->parameters;
}
/**
* Get parameters
*
* @param array $parameters
* @return static $this
*/
public function setParameters(array $parameters) {
$this->parameters = $parameters;
return $this;
}
} }
@@ -1,21 +1,82 @@
<?php <?php
namespace Pecee\SimpleRouter; namespace Pecee\SimpleRouter\Route;
use Pecee\Http\Request; use Pecee\Http\Request;
use Pecee\SimpleRouter\Exceptions\NotFoundHttpException; use Pecee\SimpleRouter\Exceptions\NotFoundHttpException;
class RouterController extends LoadableRoute implements IControllerRoute class RouteController extends LoadableRoute implements IControllerRoute
{ {
protected $defaultMethod = 'index'; protected $defaultMethod = 'index';
protected $controller; protected $controller;
protected $method; protected $method;
protected $names = [];
public function __construct($url, $controller) public function __construct($url, $controller)
{ {
$this->setUrl($url); $this->setUrl($url);
$this->setName(trim(str_replace('/', '.', $url), '/'));
$this->controller = $controller; $this->controller = $controller;
} }
/**
* Check if route has given name.
*
* @param string $name
* @return bool
*/
public function hasName($name)
{
if ($this->name === null) {
return false;
}
/* Remove method/type */
if (stripos($name, '.') !== false) {
$method = substr($name, strrpos($name, '.') + 1);
$newName = substr($name, 0, strrpos($name, '.'));
if (strtolower($this->name) === strtolower($newName) && in_array($method, $this->names)) {
return true;
}
}
return parent::hasName($name);
}
public function findUrl($method = null, $parameters = null, $name = null)
{
if (stripos($name, '.') !== false) {
$found = array_search(substr($name, strrpos($name, '.') + 1), $this->names);
if ($found !== false) {
$method = $found;
}
}
$url = '';
$parameters = (array)$parameters;
/* Remove requestType from method-name, if it exists */
if ($method !== null) {
foreach (static::$requestTypes as $requestType) {
if (stripos($method, $requestType) === 0) {
$method = substr($method, strlen($requestType));
break;
}
}
$method .= '/';
}
if ($this->getGroup() !== null && count($this->getGroup()->getDomains()) > 0) {
$url .= '//' . $this->getGroup()->getDomains()[0];
}
$url .= '/' . trim($this->getUrl(), '/') . '/' . strtolower($method) . join('/', $parameters);
return '/' . trim($url, '/') . '/';
}
public function renderRoute(Request $request) public function renderRoute(Request $request)
{ {
if ($this->getCallback() !== null && is_callable($this->getCallback())) { if ($this->getCallback() !== null && is_callable($this->getCallback())) {
@@ -109,4 +170,22 @@ class RouterController extends LoadableRoute implements IControllerRoute
return $this; return $this;
} }
/**
* Merge with information from another route.
*
* @param array $values
* @param bool $merge
* @return static
*/
public function setSettings(array $values, $merge = false)
{
if (isset($values['names'])) {
$this->names = $values['names'];
}
parent::setSettings($values, $merge);
return $this;
}
} }
@@ -1,11 +1,12 @@
<?php <?php
namespace Pecee\SimpleRouter; namespace Pecee\SimpleRouter\Route;
use Pecee\Http\Request; use Pecee\Http\Request;
class RouterGroup extends RouterEntry class RouteGroup extends Route implements IGroupRoute
{ {
protected $prefix; protected $prefix;
protected $name;
protected $domains = []; protected $domains = [];
protected $exceptionHandlers = []; protected $exceptionHandlers = [];
@@ -86,10 +87,12 @@ class RouterGroup extends RouterEntry
* Merge with information from another route. * Merge with information from another route.
* *
* @param array $values * @param array $values
* @param bool $merge
* @return static * @return static
*/ */
public function setSettings(array $values) public function setSettings(array $values, $merge = false)
{ {
if (isset($values['prefix'])) { if (isset($values['prefix'])) {
$this->setPrefix($values['prefix'] . $this->prefix); $this->setPrefix($values['prefix'] . $this->prefix);
} }
@@ -102,7 +105,15 @@ class RouterGroup extends RouterEntry
$this->setDomains((array)$values['domain']); $this->setDomains((array)$values['domain']);
} }
parent::setSettings($values); if (isset($values['as'])) {
if ($this->name !== null && $merge !== false) {
$this->name = $values['as'] . '.' . $this->name;
} else {
$this->name = $values['as'];
}
}
parent::setSettings($values, $merge);
return $this; return $this;
} }
@@ -120,6 +131,10 @@ class RouterGroup extends RouterEntry
$values['prefix'] = $this->getPrefix(); $values['prefix'] = $this->getPrefix();
} }
if ($this->name !== null) {
$values['as'] = $this->name;
}
return array_merge($values, parent::toArray()); return array_merge($values, parent::toArray());
} }
@@ -1,17 +1,62 @@
<?php <?php
namespace Pecee\SimpleRouter; namespace Pecee\SimpleRouter\Route;
use Pecee\Http\Request; use Pecee\Http\Request;
use Pecee\SimpleRouter\Exceptions\NotFoundHttpException; use Pecee\SimpleRouter\Exceptions\NotFoundHttpException;
class RouterResource extends LoadableRoute implements IControllerRoute class RouteResource extends LoadableRoute implements IControllerRoute
{ {
protected $urls = [
'index' => '',
'create' => 'create',
'store' => '',
'show' => '',
'edit' => 'edit',
'update' => '',
'destroy' => '',
];
protected $names = [];
protected $controller; protected $controller;
public function __construct($url, $controller) public function __construct($url, $controller)
{ {
$this->setUrl($url); $this->setUrl($url);
$this->controller = $controller; $this->controller = $controller;
$this->setName(trim(str_replace('/', '.', $url), '/'));
}
/**
* Check if route has given name.
*
* @param string $name
* @return bool
*/
public function hasName($name)
{
if ($this->name === null) {
return false;
}
if (strtolower($this->name) === strtolower($name)) {
return true;
}
/* Remove method/type */
if (stripos($name, '.') !== false) {
$name = substr($name, 0, strrpos($name, '.'));
}
return (strtolower($this->name) === strtolower($name));
}
public function findUrl($method = null, $parameters = null, $name = null)
{
$method = array_search($name, $this->names);
if ($method !== false) {
return rtrim($this->url . $this->urls[$method], '/') . '/';
}
return $this->url;
} }
public function renderRoute(Request $request) public function renderRoute(Request $request)
@@ -120,4 +165,39 @@ class RouterResource extends LoadableRoute implements IControllerRoute
return $this; return $this;
} }
public function setName($name)
{
$this->name = $name;
$this->names = [
'index' => $this->name . '.index',
'create' => $this->name . '.create',
'store' => $this->name . '.store',
'show' => $this->name . '.show',
'edit' => $this->name . '.edit',
'update' => $this->name . '.update',
'destroy' => $this->name . '.destroy',
];
return $this;
}
/**
* Merge with information from another route.
*
* @param array $values
* @param bool $merge
* @return static
*/
public function setSettings(array $values, $merge = false)
{
if (isset($values['names'])) {
$this->names = $values['names'];
}
parent::setSettings($values, $merge);
return $this;
}
} }
@@ -1,9 +1,9 @@
<?php <?php
namespace Pecee\SimpleRouter; namespace Pecee\SimpleRouter\Route;
use Pecee\Http\Request; use Pecee\Http\Request;
class RouterRoute extends LoadableRoute class RouteUrl extends LoadableRoute
{ {
public function __construct($url, $callback) public function __construct($url, $callback)
{ {
@@ -6,8 +6,12 @@ use Pecee\Http\Middleware\BaseCsrfVerifier;
use Pecee\Http\Request; use Pecee\Http\Request;
use Pecee\SimpleRouter\Exceptions\HttpException; use Pecee\SimpleRouter\Exceptions\HttpException;
use Pecee\SimpleRouter\Exceptions\NotFoundHttpException; use Pecee\SimpleRouter\Exceptions\NotFoundHttpException;
use Pecee\SimpleRouter\Route\IControllerRoute;
use Pecee\SimpleRouter\Route\IGroupRoute;
use Pecee\SimpleRouter\Route\ILoadableRoute;
use Pecee\SimpleRouter\Route\IRoute;
class RouterBase class Router
{ {
/** /**
@@ -67,7 +71,7 @@ class RouterBase
/** /**
* The current loaded route * The current loaded route
* @var RouterRoute|null * @var ILoadableRoute|null
*/ */
protected $loadedRoute; protected $loadedRoute;
@@ -133,13 +137,13 @@ class RouterBase
return $route; return $route;
} }
protected function processRoutes(array $routes, RouterGroup $group = null, IRoute $parent = null) protected function processRoutes(array $routes, IGroupRoute $group = null, IRoute $parent = null)
{ {
// Loop through each route-request // Loop through each route-request
/* @var $route IRoute */ /* @var $route IRoute */
foreach ($routes as $route) { foreach ($routes as $route) {
if ($route instanceof RouterGroup) { if ($route instanceof IGroupRoute) {
$group = $route; $group = $route;
@@ -173,7 +177,7 @@ class RouterBase
$route->setParent($parent); $route->setParent($parent);
/* Add/merge parent settings with child */ /* Add/merge parent settings with child */
$route->setSettings($parent->toArray()); $route->setSettings($parent->toArray(), true);
} }
@@ -204,7 +208,7 @@ class RouterBase
/* Initialize boot-managers */ /* Initialize boot-managers */
if (count($this->bootManagers) > 0) { if (count($this->bootManagers) > 0) {
/* @var $manager RouterBootManager */ /* @var $manager IRouterBootManager */
foreach ($this->bootManagers as $manager) { foreach ($this->bootManagers as $manager) {
$this->request = $manager->boot($this->request); $this->request = $manager->boot($this->request);
@@ -315,65 +319,15 @@ class RouterBase
return ''; return '';
} }
protected function processUrl(LoadableRoute $route, $method = null, $parameters = null, array $getParams = [])
{
$url = '';
$parameters = (array)$parameters;
if ($route->getGroup() !== null && count($route->getGroup()->getDomains()) > 0) {
$url .= '//' . $route->getGroup()->getDomains()[0];
}
$url .= '/' . trim($route->getUrl(), '/');
if ($route instanceof IControllerRoute && $method !== null) {
$url .= '/' . $method . '/';
if (count($parameters) > 0) {
$url .= join('/', $parameters);
}
} else {
$params = array_merge($route->getParameters(), $parameters);
/* Url that contains parameters that aren't recognized */
$unknownParams = [];
/* Let's parse the values of any {} parameter in the url */
foreach ($params as $param => $value) {
$value = (isset($parameters[$param])) ? $parameters[$param] : $value;
/* Create the param string - {} */
$param1 = LoadableRoute::PARAMETER_MODIFIERS[0] . $param . LoadableRoute::PARAMETER_MODIFIERS[1];
/* Create the param string with the optional symbol - {?} */
$param2 = LoadableRoute::PARAMETER_MODIFIERS[0] . $param . LoadableRoute::PARAMETER_OPTIONAL_SYMBOL . LoadableRoute::PARAMETER_MODIFIERS[1];
if (stripos($url, $param1) !== false || stripos($url, $param) !== false) {
$url = str_ireplace([$param1, $param2], $value, $url);
} else {
$unknownParams[$param] = $value;
}
}
$url = rtrim($url, '/') . '/' . join('/', $unknownParams);
}
return rtrim($url, '/') . '/' . $this->arrayToParams($getParams);
}
/** /**
* Find route by alias, class, callback or method. * Find route by alias, class, callback or method.
* *
* @param string $name * @param string $name
* @return LoadableRoute|null * @return ILoadableRoute|null
*/ */
public function findRoute($name) public function findRoute($name)
{ {
/* @var $route LoadableRoute */ /* @var $route ILoadableRoute */
foreach ($this->processedRoutes as $route) { foreach ($this->processedRoutes as $route) {
/* Check if the name matches with a name on the route. Should match either router alias or controller alias. */ /* Check if the name matches with a name on the route. Should match either router alias or controller alias. */
@@ -452,14 +406,14 @@ class RouterBase
/* If nothing is defined and a route is loaded we use that */ /* If nothing is defined and a route is loaded we use that */
if ($name === null && $this->loadedRoute !== null) { if ($name === null && $this->loadedRoute !== null) {
return $this->processUrl($this->loadedRoute, $this->loadedRoute->getMethod(), $parameters, $getParams); return $this->loadedRoute->findUrl($this->loadedRoute->getMethod(), $parameters, $name) . $this->arrayToParams($getParams);
} }
/* We try to find a match on the given name */ /* We try to find a match on the given name */
$route = $this->findRoute($name); $route = $this->findRoute($name);
if ($route !== null) { if ($route !== null) {
return $this->processUrl($route, $route->getMethod(), $parameters, $getParams); return $route->findUrl($route->getMethod(), $parameters, $name) . $this->arrayToParams($getParams);
} }
/* Using @ is most definitely a controller@method or alias@method */ /* Using @ is most definitely a controller@method or alias@method */
@@ -468,17 +422,17 @@ class RouterBase
/* Loop through all the routes to see if we can find a match */ /* Loop through all the routes to see if we can find a match */
/* @var $route LoadableRoute */ /* @var $route ILoadableRoute */
foreach ($this->processedRoutes as $route) { foreach ($this->processedRoutes as $route) {
/* Check if the route contains the name/alias */ /* Check if the route contains the name/alias */
if ($route->hasName($controller)) { if ($route->hasName($controller)) {
return $this->processUrl($route, $method, $parameters, $getParams); return $route->findUrl($method, $parameters, $name) . $this->arrayToParams($getParams);
} }
/* Check if the route controller is equal to the name */ /* Check if the route controller is equal to the name */
if ($route instanceof IControllerRoute && strtolower($route->getController()) === strtolower($controller)) { if ($route instanceof IControllerRoute && strtolower($route->getController()) === strtolower($controller)) {
return $this->processUrl($route, $method, $parameters, $getParams); return $route->findUrl($method, $parameters, $name) . $this->arrayToParams($getParams);
} }
} }
@@ -509,9 +463,9 @@ class RouterBase
/** /**
* Add bootmanager * Add bootmanager
* @param RouterBootManager $bootManager * @param IRouterBootManager $bootManager
*/ */
public function addBootManager(RouterBootManager $bootManager) public function addBootManager(IRouterBootManager $bootManager)
{ {
$this->bootManagers[] = $bootManager; $this->bootManagers[] = $bootManager;
} }
@@ -558,7 +512,7 @@ class RouterBase
/** /**
* Get loaded route * Get loaded route
* @return RouterRoute|null * @return ILoadableRoute|null
*/ */
public function getLoadedRoute() public function getLoadedRoute()
{ {
@@ -1,9 +0,0 @@
<?php
namespace Pecee\SimpleRouter;
use Pecee\Http\Request;
abstract class RouterBootManager
{
abstract public function boot(Request $request);
}
+31 -24
View File
@@ -3,7 +3,9 @@
* --------------------------- * ---------------------------
* Router helper class * Router helper class
* --------------------------- * ---------------------------
* This class is added so calls can be made statically like Router::get() making the code look more pretty. *
* This class is added so calls can be made statically like Router::get() making the code look pretty.
* It also adds some extra functionality like default-namespace.
*/ */
namespace Pecee\SimpleRouter; namespace Pecee\SimpleRouter;
@@ -11,6 +13,11 @@ use Pecee\Http\Middleware\BaseCsrfVerifier;
use Pecee\Http\Response; use Pecee\Http\Response;
use Pecee\SimpleRouter\Exceptions\HttpException; use Pecee\SimpleRouter\Exceptions\HttpException;
use Pecee\SimpleRouter\Exceptions\NotFoundHttpException; use Pecee\SimpleRouter\Exceptions\NotFoundHttpException;
use Pecee\SimpleRouter\Route\IRoute;
use Pecee\SimpleRouter\Route\RouteController;
use Pecee\SimpleRouter\Route\RouteGroup;
use Pecee\SimpleRouter\Route\RouteResource;
use Pecee\SimpleRouter\Route\RouteUrl;
class SimpleRouter class SimpleRouter
{ {
@@ -61,9 +68,9 @@ class SimpleRouter
* Boot managers allows you to alter the routes before the routing occurs. * Boot managers allows you to alter the routes before the routing occurs.
* Perfect if you want to load pretty-urls from a file or database. * Perfect if you want to load pretty-urls from a file or database.
* *
* @param RouterBootManager $bootManager * @param IRouterBootManager $bootManager
*/ */
public static function addBootManager(RouterBootManager $bootManager) public static function addBootManager(IRouterBootManager $bootManager)
{ {
static::router()->addBootManager($bootManager); static::router()->addBootManager($bootManager);
} }
@@ -74,7 +81,7 @@ class SimpleRouter
* @param string $url * @param string $url
* @param string|\Closure $callback * @param string|\Closure $callback
* @param array|null $settings * @param array|null $settings
* @return RouterRoute * @return RouteUrl
*/ */
public static function get($url, $callback, array $settings = null) public static function get($url, $callback, array $settings = null)
{ {
@@ -87,7 +94,7 @@ class SimpleRouter
* @param string $url * @param string $url
* @param string|\Closure $callback * @param string|\Closure $callback
* @param array|null $settings * @param array|null $settings
* @return RouterRoute * @return RouteUrl
*/ */
public static function post($url, $callback, array $settings = null) public static function post($url, $callback, array $settings = null)
{ {
@@ -100,7 +107,7 @@ class SimpleRouter
* @param string $url * @param string $url
* @param string|\Closure $callback * @param string|\Closure $callback
* @param array|null $settings * @param array|null $settings
* @return RouterRoute * @return RouteUrl
*/ */
public static function put($url, $callback, array $settings = null) public static function put($url, $callback, array $settings = null)
{ {
@@ -113,7 +120,7 @@ class SimpleRouter
* @param string $url * @param string $url
* @param string|\Closure $callback * @param string|\Closure $callback
* @param array|null $settings * @param array|null $settings
* @return RouterRoute * @return RouteUrl
*/ */
public static function patch($url, $callback, array $settings = null) public static function patch($url, $callback, array $settings = null)
{ {
@@ -126,7 +133,7 @@ class SimpleRouter
* @param string $url * @param string $url
* @param string|\Closure $callback * @param string|\Closure $callback
* @param array|null $settings * @param array|null $settings
* @return RouterRoute * @return RouteUrl
*/ */
public static function options($url, $callback, array $settings = null) public static function options($url, $callback, array $settings = null)
{ {
@@ -139,7 +146,7 @@ class SimpleRouter
* @param string $url * @param string $url
* @param string|\Closure $callback * @param string|\Closure $callback
* @param array|null $settings * @param array|null $settings
* @return RouterRoute * @return RouteUrl
*/ */
public static function delete($url, $callback, array $settings = null) public static function delete($url, $callback, array $settings = null)
{ {
@@ -152,11 +159,11 @@ class SimpleRouter
* @param array $settings * @param array $settings
* @param \Closure $callback * @param \Closure $callback
* @throws \InvalidArgumentException * @throws \InvalidArgumentException
* @return RouterGroup * @return RouteGroup
*/ */
public static function group(array $settings = [], \Closure $callback) public static function group(array $settings = [], \Closure $callback)
{ {
$group = new RouterGroup(); $group = new RouteGroup();
$group->setCallback($callback); $group->setCallback($callback);
$group->setSettings($settings); $group->setSettings($settings);
@@ -176,7 +183,7 @@ class SimpleRouter
* @param callable $callback * @param callable $callback
* @param array|null $settings * @param array|null $settings
* @see SimpleRouter::form * @see SimpleRouter::form
* @return RouterRoute * @return RouteUrl
*/ */
public static function basic($url, $callback, array $settings = null) public static function basic($url, $callback, array $settings = null)
{ {
@@ -191,7 +198,7 @@ class SimpleRouter
* @param string|\Closure $callback * @param string|\Closure $callback
* @param array|null $settings * @param array|null $settings
* @see SimpleRouter::form * @see SimpleRouter::form
* @return RouterRoute * @return RouteUrl
*/ */
public static function form($url, $callback, array $settings = null) public static function form($url, $callback, array $settings = null)
{ {
@@ -205,11 +212,11 @@ class SimpleRouter
* @param string $url * @param string $url
* @param string|\Closure $callback * @param string|\Closure $callback
* @param array|null $settings * @param array|null $settings
* @return RouterRoute * @return RouteUrl
*/ */
public static function match(array $requestMethods, $url, $callback, array $settings = null) public static function match(array $requestMethods, $url, $callback, array $settings = null)
{ {
$route = new RouterRoute($url, $callback); $route = new RouteUrl($url, $callback);
$route->setRequestMethods($requestMethods); $route->setRequestMethods($requestMethods);
$route = static::addDefaultNamespace($route); $route = static::addDefaultNamespace($route);
@@ -228,11 +235,11 @@ class SimpleRouter
* @param string $url * @param string $url
* @param string|\Closure $callback * @param string|\Closure $callback
* @param array|null $settings * @param array|null $settings
* @return RouterRoute * @return RouteUrl
*/ */
public static function all($url, $callback, array $settings = null) public static function all($url, $callback, array $settings = null)
{ {
$route = new RouterRoute($url, $callback); $route = new RouteUrl($url, $callback);
$route = static::addDefaultNamespace($route); $route = static::addDefaultNamespace($route);
if ($settings !== null) { if ($settings !== null) {
@@ -250,11 +257,11 @@ class SimpleRouter
* @param string $url * @param string $url
* @param string $controller * @param string $controller
* @param array|null $settings * @param array|null $settings
* @return RouterController * @return RouteController
*/ */
public static function controller($url, $controller, array $settings = null) public static function controller($url, $controller, array $settings = null)
{ {
$route = new RouterController($url, $controller); $route = new RouteController($url, $controller);
$route = static::addDefaultNamespace($route); $route = static::addDefaultNamespace($route);
if ($settings !== null) { if ($settings !== null) {
@@ -272,11 +279,11 @@ class SimpleRouter
* @param string $url * @param string $url
* @param string $controller * @param string $controller
* @param array|null $settings * @param array|null $settings
* @return RouterResource * @return RouteResource
*/ */
public static function resource($url, $controller, array $settings = null) public static function resource($url, $controller, array $settings = null)
{ {
$route = new RouterResource($url, $controller); $route = new RouteResource($url, $controller);
if ($settings !== null) { if ($settings !== null) {
$route->setSettings($settings); $route->setSettings($settings);
@@ -351,7 +358,7 @@ class SimpleRouter
*/ */
public static function response() public static function response()
{ {
if(static::$response === null) { if (static::$response === null) {
static::$response = new Response(static::request()); static::$response = new Response(static::request());
} }
@@ -361,11 +368,11 @@ class SimpleRouter
/** /**
* Returns the router instance * Returns the router instance
* *
* @return RouterBase * @return Router
*/ */
public static function router() public static function router()
{ {
return RouterBase::getInstance(); return Router::getInstance();
} }
/** /**
+1 -1
View File
@@ -6,7 +6,7 @@ use Pecee\Http\Request;
class DummyMiddleware implements IMiddleware class DummyMiddleware implements IMiddleware
{ {
public function handle(Request $request, \Pecee\SimpleRouter\RouterEntry &$route = null) public function handle(Request $request, \Pecee\SimpleRouter\Route\ILoadableRoute &$route)
{ {
throw new MiddlewareLoadedException('Middleware loaded!'); throw new MiddlewareLoadedException('Middleware loaded!');
} }
+1 -1
View File
@@ -2,7 +2,7 @@
class ExceptionHandler implements \Pecee\Handlers\IExceptionHandler class ExceptionHandler implements \Pecee\Handlers\IExceptionHandler
{ {
public function handleError(\Pecee\Http\Request $request, \Pecee\SimpleRouter\RouterEntry &$route = null, \Exception $error) public function handleError(\Pecee\Http\Request $request, \Pecee\SimpleRouter\Route\ILoadableRoute &$route = null, \Exception $error)
{ {
throw $error; throw $error;
} }
-6
View File
@@ -85,17 +85,11 @@ class GroupTest extends PHPUnit_Framework_TestCase
// Test method name // Test method name
SimpleRouter::get('/my/fancy/url/2', 'DummyController@start')->setName('fancy2'); SimpleRouter::get('/my/fancy/url/2', 'DummyController@start')->setName('fancy2');
// Test multiple names
SimpleRouter::get('/my/fancy/url/3', 'DummyController@start', ['as' => ['fancy3', 'fancy4']]);
SimpleRouter::start(); SimpleRouter::start();
$this->assertEquals('/my/fancy/url/1/', SimpleRouter::getRoute('fancy1')); $this->assertEquals('/my/fancy/url/1/', SimpleRouter::getRoute('fancy1'));
$this->assertEquals('/my/fancy/url/2/', SimpleRouter::getRoute('fancy2')); $this->assertEquals('/my/fancy/url/2/', SimpleRouter::getRoute('fancy2'));
$this->assertEquals('/my/fancy/url/3/', SimpleRouter::getRoute('fancy3'));
$this->assertEquals('/my/fancy/url/3/', SimpleRouter::getRoute('fancy4'));
} }
} }
+33 -15
View File
@@ -23,60 +23,78 @@ class RouterUrlTest extends PHPUnit_Framework_TestCase
// Match normal route on alias // Match normal route on alias
SimpleRouter::get('/', 'DummyController@silent', ['as' => 'home']); SimpleRouter::get('/', 'DummyController@silent', ['as' => 'home']);
SimpleRouter::group(['prefix' => '/admin'], function() { SimpleRouter::get('/about', 'DummyController@about');
SimpleRouter::group(['prefix' => '/admin', 'as' => 'admin'], function() {
// Match route with prefix on alias // Match route with prefix on alias
SimpleRouter::get('/{id?}', 'DummyController@start', ['as' => 'admin.home']); SimpleRouter::get('/{id?}', 'DummyController@start', ['as' => 'home']);
// Match controller with prefix and alias // Match controller with prefix and alias
SimpleRouter::controller('/users', 'DummyController', ['as' => 'admin.users']); SimpleRouter::controller('/users', 'DummyController', ['as' => 'users']);
// Match controller with prefix and NO alias // Match controller with prefix and NO alias
SimpleRouter::controller('/pages', 'DummyController'); SimpleRouter::controller('/pages', 'DummyController');
}); });
SimpleRouter::group(['prefix' => 'api', 'as' => 'api'], function() {
// Match resource controller
SimpleRouter::resource('phones', 'DummyController');
});
SimpleRouter::controller('gadgets', 'DummyController', ['names' => ['getIphoneInfo' => 'iphone']]);
// Match controller with no prefix and no alias // Match controller with no prefix and no alias
SimpleRouter::controller('/cats', 'CatsController'); SimpleRouter::controller('/cats', 'CatsController');
// Pretend to load page // Pretend to load page
SimpleRouter::start(); SimpleRouter::start();
$this->assertEquals('/gadgets/iphoneinfo/', $this->getUrl('gadgets.iphone'));
$this->assertEquals('/api/phones/create/', $this->getUrl('api.phones.create'));
// Should match / // Should match /
$this->assertEquals($this->getUrl('home'), '/'); $this->assertEquals('/', $this->getUrl('home'));
// Should match /about/
$this->assertEquals('/about/', $this->getUrl('DummyController@about'));
// Should match /admin/ // Should match /admin/
$this->assertEquals($this->getUrl('DummyController@start'), '/admin/'); $this->assertEquals('/admin/', $this->getUrl('DummyController@start'));
// Should match /admin/ // Should match /admin/
$this->assertEquals($this->getUrl('admin.home'), '/admin/'); $this->assertEquals('/admin/', $this->getUrl('admin.home'));
// Should match /admin/2/ // Should match /admin/2/
$this->assertEquals($this->getUrl('admin.home', ['id' => 2]), '/admin/2/'); $this->assertEquals('/admin/2/', $this->getUrl('admin.home', ['id' => 2]));
// Should match /admin/users/ // Should match /admin/users/
$this->assertEquals($this->getUrl('admin.users'), '/admin/users/'); $this->assertEquals('/admin/users/', $this->getUrl('admin.users'));
// Should match /admin/users/home/ // Should match /admin/users/home/
$this->assertEquals($this->getUrl('admin.users@home'), '/admin/users/home/'); $this->assertEquals('/admin/users/home/', $this->getUrl('admin.users@home'));
// Should match /cats/ // Should match /cats/
$this->assertEquals($this->getUrl('CatsController'), '/cats/'); $this->assertEquals('/cats/', $this->getUrl('CatsController'));
// Should match /cats/view/ // Should match /cats/view/
$this->assertEquals($this->getUrl('CatsController', 'view'), '/cats/view/'); $this->assertEquals('/cats/view/', $this->getUrl('CatsController', 'view'));
// Should match /cats/view/ // Should match /cats/view/
$this->assertEquals($this->getUrl('CatsController', ['view']), '/cats/view/'); //$this->assertEquals('/cats/view/', $this->getUrl('CatsController', ['view']));
// Should match /cats/view/666 // Should match /cats/view/666
$this->assertEquals($this->getUrl('CatsController@view', ['666']), '/cats/view/666/'); $this->assertEquals('/cats/view/666/', $this->getUrl('CatsController@getView', ['666']));
// Should match /funny/man/ // Should match /funny/man/
$this->assertEquals($this->getUrl('/funny/man'), '/funny/man/'); $this->assertEquals('/funny/man/', $this->getUrl('/funny/man'));
// Should match /?jackdaniels=true&cola=yeah // Should match /?jackdaniels=true&cola=yeah
$this->assertEquals($this->getUrl('home', null, ['jackdaniels' => 'true', 'cola' => 'yeah']), '/?jackdaniels=true&cola=yeah'); $this->assertEquals('/?jackdaniels=true&cola=yeah', $this->getUrl('home', null, ['jackdaniels' => 'true', 'cola' => 'yeah']));
} }