mirror of
https://github.com/skipperbent/simple-php-router.git
synced 2026-06-17 08:47:52 +00:00
Development
- Fixed global regex match not working properly. - Feature: added option to change regular expression used for parameters on routes. - Added unit-tests for custom parameter regular expression. - Updated documentation to reflect new features.
This commit is contained in:
@@ -70,12 +70,13 @@ If you want a great new feature or experience any issues what-so-ever, please fe
|
|||||||
- [Get all parameters](#get-all-parameters)
|
- [Get all parameters](#get-all-parameters)
|
||||||
|
|
||||||
- [Advanced](#advanced)
|
- [Advanced](#advanced)
|
||||||
- [Bootmanager: loading routes dynamically](#bootmanager-loading-routes-dynamically)
|
|
||||||
- [Url rewriting](#url-rewriting)
|
- [Url rewriting](#url-rewriting)
|
||||||
- [Rewrite using callback](#rewrite-using-callback)
|
- [Rewrite using callback](#rewrite-using-callback)
|
||||||
- [Rewrite using url](#rewrite-using-url)
|
- [Rewrite using url](#rewrite-using-url)
|
||||||
|
- [Bootmanager: loading routes dynamically](#bootmanager-loading-routes-dynamically)
|
||||||
- [Adding routes manually](#adding-routes-manually)
|
- [Adding routes manually](#adding-routes-manually)
|
||||||
|
- [Parameters](#parameters)
|
||||||
|
- [Custom default regex for matching parameters](#custom-default-regex-for-matching-parameters)
|
||||||
- [Extending](#extending)
|
- [Extending](#extending)
|
||||||
|
|
||||||
- [Credits](#credits)
|
- [Credits](#credits)
|
||||||
@@ -902,11 +903,9 @@ $request->setRewriteCallback('Example\MyCustomClass@hello');
|
|||||||
$request->setRewriteUrl('/my-rewrite-url');
|
$request->setRewriteUrl('/my-rewrite-url');
|
||||||
```
|
```
|
||||||
|
|
||||||
### Examples
|
**Note:** It's only possible to change the route BEFORE the route has initially been rendered. You can use the `Request` object to manipulate the route which are about to be loaded.
|
||||||
|
|
||||||
It's only possible to change the route BEFORE the route has initially been rendered. You can use the `Request` object to manipulate the route which are about to be loaded.
|
### Rewrite using callback
|
||||||
|
|
||||||
#### Rewrite using callback
|
|
||||||
|
|
||||||
This method is most efficient, as it will render the route immediately.
|
This method is most efficient, as it will render the route immediately.
|
||||||
|
|
||||||
@@ -922,7 +921,7 @@ The example below will render `DefaultController@notFound` regardless of the url
|
|||||||
|
|
||||||
**NOTE: Use this method if you want to load another controller. No additional middlewares or rules will be loaded.**
|
**NOTE: Use this method if you want to load another controller. No additional middlewares or rules will be loaded.**
|
||||||
|
|
||||||
#### Middleware example
|
##### Middleware example
|
||||||
|
|
||||||
```php
|
```php
|
||||||
namespace Demo\Middlewares;
|
namespace Demo\Middlewares;
|
||||||
@@ -942,7 +941,7 @@ class CustomMiddleware implements IMiddleware {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Exception handler example
|
##### Exception handler example
|
||||||
|
|
||||||
```php
|
```php
|
||||||
namespace Demo\Handlers;
|
namespace Demo\Handlers;
|
||||||
@@ -977,7 +976,7 @@ class CustomExceptionHandler implements IExceptionHandler
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Rewrite using url
|
### Rewrite using url
|
||||||
|
|
||||||
The example below will cause the router to reload the request and reinitialize all the routes. This method is slower, but will ensure that all middlewares and rules for the route is loaded.
|
The example below will cause the router to reload the request and reinitialize all the routes. This method is slower, but will ensure that all middlewares and rules for the route is loaded.
|
||||||
|
|
||||||
@@ -988,7 +987,7 @@ We are using the `url()` helper function to get the uri to another route added i
|
|||||||
|
|
||||||
**NOTE: Use this method if you want to fully load another route using it's settings (request method, middlewares etc).**
|
**NOTE: Use this method if you want to fully load another route using it's settings (request method, middlewares etc).**
|
||||||
|
|
||||||
#### Middleware example
|
##### Middleware example
|
||||||
|
|
||||||
The example below will redirect the request to the `home`-route.
|
The example below will redirect the request to the `home`-route.
|
||||||
|
|
||||||
@@ -1009,7 +1008,7 @@ class CustomMiddleware implements IMiddleware {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
# Bootmanager: loading routes dynamically
|
### Bootmanager: loading routes dynamically
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
@@ -1055,7 +1054,7 @@ The last thing we need to do, is to add our custom boot-manager to the ```routes
|
|||||||
SimpleRouter::addBootManager(new CustomRouterRules());
|
SimpleRouter::addBootManager(new CustomRouterRules());
|
||||||
```
|
```
|
||||||
|
|
||||||
## Adding routes manually
|
### Adding routes manually
|
||||||
|
|
||||||
The ```SimpleRouter``` class referenced in the previous example, is just a simple helper class that knows how to communicate with the ```Router``` 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.
|
||||||
@@ -1081,6 +1080,39 @@ $route->setPrefix('v1');
|
|||||||
$router->addRoute($route);
|
$router->addRoute($route);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Parameters
|
||||||
|
|
||||||
|
This section contains advanced tips & tricks on extending the usage for parameters.
|
||||||
|
|
||||||
|
### Custom default regex for matching parameters
|
||||||
|
|
||||||
|
By default simple-php-router uses the `\w` regular expression when matching parameters.
|
||||||
|
This decision was made with speed and reliability in mind, as this match will match both letters, number and most of the used symbols on the internet.
|
||||||
|
|
||||||
|
However, sometimes it can be nessesary to add a custom regular expression to match more advanced characters like `-` etc.
|
||||||
|
|
||||||
|
Instead of adding a custom regular expression to all your parameters, you can simply add a global regular expression which will be used on all the parameters on the route.
|
||||||
|
|
||||||
|
**Note:** If you the regular expression to be available across, we recommend using the global parameter on a group as demonstrated in the examples below.
|
||||||
|
|
||||||
|
#### Route
|
||||||
|
|
||||||
|
This example will ensure that all parameters use the `[\w\-]+` regular expression when parsing.
|
||||||
|
|
||||||
|
```php
|
||||||
|
SimpleRouter::get('/path/{parameter}', 'VideoController@home', ['defaultParameterRegex' => '[\w\-]+']);
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also apply this setting to a group if you need multiple routes to use your custom regular expression when parsing parameters.
|
||||||
|
|
||||||
|
```php
|
||||||
|
SimpleRouter::group(['defaultParameterRegex' => '[\w\-]+'], function() {
|
||||||
|
|
||||||
|
SimpleRouter::get('/path/{parameter}', 'VideoController@home');
|
||||||
|
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
## Extending
|
## Extending
|
||||||
|
|
||||||
This is a simple example of an integration into a framework.
|
This is a simple example of an integration into a framework.
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Pecee\SimpleRouter\Route;
|
namespace Pecee\SimpleRouter\Route;
|
||||||
|
|
||||||
use Pecee\Http\Middleware\IMiddleware;
|
use Pecee\Http\Middleware\IMiddleware;
|
||||||
@@ -54,17 +55,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$parameters = [];
|
return (preg_match($this->regex, $request->getHost() . $url) > 0);
|
||||||
|
|
||||||
if (preg_match($this->regex, $request->getHost() . $url, $parameters) > 0) {
|
|
||||||
|
|
||||||
/* Remove global match */
|
|
||||||
$this->parameters = array_slice($parameters, 1);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -79,7 +70,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute
|
|||||||
|
|
||||||
if (strpos($this->url, $this->paramModifiers[0]) !== false) {
|
if (strpos($this->url, $this->paramModifiers[0]) !== false) {
|
||||||
|
|
||||||
$regex = sprintf(static::PARAMETERS_REGEX_MATCH, $this->paramModifiers[0], $this->paramOptionalSymbol, $this->paramModifiers[1]);
|
$regex = sprintf(static::PARAMETERS_REGEX_FORMAT, $this->paramModifiers[0], $this->paramOptionalSymbol, $this->paramModifiers[1]);
|
||||||
|
|
||||||
if (preg_match_all('/' . $regex . '/', $this->url, $matches)) {
|
if (preg_match_all('/' . $regex . '/', $this->url, $matches)) {
|
||||||
$this->parameters = array_fill_keys($matches[1], null);
|
$this->parameters = array_fill_keys($matches[1], null);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Pecee\SimpleRouter\Route;
|
namespace Pecee\SimpleRouter\Route;
|
||||||
|
|
||||||
use Pecee\Http\Request;
|
use Pecee\Http\Request;
|
||||||
@@ -6,7 +7,8 @@ use Pecee\SimpleRouter\Exceptions\NotFoundHttpException;
|
|||||||
|
|
||||||
abstract class Route implements IRoute
|
abstract class Route implements IRoute
|
||||||
{
|
{
|
||||||
const PARAMETERS_REGEX_MATCH = '%s([\w]+)(\%s?)%s';
|
const PARAMETERS_REGEX_FORMAT = '%s([\w]+)(\%s?)%s';
|
||||||
|
const PARAMETERS_DEFAULT_REGEX = '[\w]+';
|
||||||
|
|
||||||
const REQUEST_TYPE_GET = 'get';
|
const REQUEST_TYPE_GET = 'get';
|
||||||
const REQUEST_TYPE_POST = 'post';
|
const REQUEST_TYPE_POST = 'post';
|
||||||
@@ -31,6 +33,7 @@ abstract class Route implements IRoute
|
|||||||
* @var bool
|
* @var bool
|
||||||
*/
|
*/
|
||||||
protected $filterEmptyParams = false;
|
protected $filterEmptyParams = false;
|
||||||
|
protected $defaultParameterRegex = null;
|
||||||
protected $paramModifiers = '{}';
|
protected $paramModifiers = '{}';
|
||||||
protected $paramOptionalSymbol = '?';
|
protected $paramOptionalSymbol = '?';
|
||||||
protected $group;
|
protected $group;
|
||||||
@@ -94,9 +97,9 @@ abstract class Route implements IRoute
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function parseParameters($route, $url, $parameterRegex = '[\w]+')
|
protected function parseParameters($route, $url, $parameterRegex = null)
|
||||||
{
|
{
|
||||||
$regex = sprintf(static::PARAMETERS_REGEX_MATCH, $this->paramModifiers[0], $this->paramOptionalSymbol, $this->paramModifiers[1]);
|
$regex = sprintf(static::PARAMETERS_REGEX_FORMAT, $this->paramModifiers[0], $this->paramOptionalSymbol, $this->paramModifiers[1]);
|
||||||
|
|
||||||
$parameters = [];
|
$parameters = [];
|
||||||
|
|
||||||
@@ -111,7 +114,20 @@ abstract class Route implements IRoute
|
|||||||
if ($key < count($parameters[1])) {
|
if ($key < count($parameters[1])) {
|
||||||
|
|
||||||
$name = $parameters[1][$key];
|
$name = $parameters[1][$key];
|
||||||
$regex = isset($this->where[$name]) ? $this->where[$name] : $parameterRegex;
|
|
||||||
|
/* If custom regex is defined, use that */
|
||||||
|
if (isset($this->where[$name]) === true) {
|
||||||
|
$regex = $this->where[$name];
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* If method specific regex is defined use that, otherwise use the default parameter regex */
|
||||||
|
if ($parameterRegex !== null) {
|
||||||
|
$regex = $parameterRegex;
|
||||||
|
} else {
|
||||||
|
$regex = ($this->defaultParameterRegex === null) ? static::PARAMETERS_DEFAULT_REGEX : $this->defaultParameterRegex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$regex = sprintf('\-?\/?(?P<%s>%s)', $name, $regex) . $parameters[2][$key];
|
$regex = sprintf('\-?\/?(?P<%s>%s)', $name, $regex) . $parameters[2][$key];
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -129,7 +145,7 @@ abstract class Route implements IRoute
|
|||||||
|
|
||||||
$values = [];
|
$values = [];
|
||||||
|
|
||||||
if (isset($parameters[1])) {
|
if (isset($parameters[1]) === true) {
|
||||||
|
|
||||||
/* Only take matched parameters with name */
|
/* Only take matched parameters with name */
|
||||||
foreach ($parameters[1] as $name) {
|
foreach ($parameters[1] as $name) {
|
||||||
@@ -343,6 +359,10 @@ abstract class Route implements IRoute
|
|||||||
$values['middleware'] = $this->middlewares;
|
$values['middleware'] = $this->middlewares;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->defaultParameterRegex !== null) {
|
||||||
|
$values['defaultParameterRegex'] = $this->defaultParameterRegex;
|
||||||
|
}
|
||||||
|
|
||||||
return $values;
|
return $values;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -376,6 +396,10 @@ abstract class Route implements IRoute
|
|||||||
$this->setMiddlewares(array_merge((array)$values['middleware'], $this->middlewares));
|
$this->setMiddlewares(array_merge((array)$values['middleware'], $this->middlewares));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($values['defaultParameterRegex'])) {
|
||||||
|
$this->setDefaultParameterRegex($values['defaultParameterRegex']);
|
||||||
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -487,4 +511,28 @@ abstract class Route implements IRoute
|
|||||||
return $this->middlewares;
|
return $this->middlewares;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set default regular expression used when matching parameters.
|
||||||
|
* This is used when no custom parameter regex is found.
|
||||||
|
*
|
||||||
|
* @param string $regex
|
||||||
|
* @return static $this
|
||||||
|
*/
|
||||||
|
public function setDefaultParameterRegex($regex)
|
||||||
|
{
|
||||||
|
$this->defaultParameterRegex = $regex;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get default regular expression used when matching parameters.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDefaultParameterRegex()
|
||||||
|
{
|
||||||
|
return $this->defaultParameterRegex;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Pecee\SimpleRouter\Route;
|
namespace Pecee\SimpleRouter\Route;
|
||||||
|
|
||||||
use Pecee\Http\Request;
|
use Pecee\Http\Request;
|
||||||
@@ -90,8 +91,11 @@ class RouteResource extends LoadableRoute implements IControllerRoute
|
|||||||
|
|
||||||
$route = rtrim($this->url, '/') . '/{id?}/{action?}';
|
$route = rtrim($this->url, '/') . '/{id?}/{action?}';
|
||||||
|
|
||||||
|
/* Parse parameters from current route */
|
||||||
$this->parameters = $this->parseParameters($route, $url);
|
$this->parameters = $this->parseParameters($route, $url);
|
||||||
if ($this->parameters === null) {
|
|
||||||
|
/* If no custom regular expression or parameters was found on this route, we stop */
|
||||||
|
if ($regexMatch === null && $this->parameters === null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Pecee\SimpleRouter\Route;
|
namespace Pecee\SimpleRouter\Route;
|
||||||
|
|
||||||
use Pecee\Http\Request;
|
use Pecee\Http\Request;
|
||||||
@@ -18,17 +19,21 @@ class RouteUrl extends LoadableRoute
|
|||||||
|
|
||||||
/* Match global regular-expression for route */
|
/* Match global regular-expression for route */
|
||||||
$regexMatch = $this->matchRegex($request, $url);
|
$regexMatch = $this->matchRegex($request, $url);
|
||||||
|
|
||||||
if ($regexMatch === false) {
|
if ($regexMatch === false) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make regular expression based on route */
|
/* Parse parameters from current route */
|
||||||
$parameters = $this->parseParameters($this->url, $url);
|
$parameters = $this->parseParameters($this->url, $url);
|
||||||
if ($parameters === null) {
|
|
||||||
|
/* If no custom regular expression or parameters was found on this route, we stop */
|
||||||
|
if ($regexMatch === null && $parameters === null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->setParameters($parameters);
|
/* Set the parameters */
|
||||||
|
$this->setParameters((array)$parameters);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,4 +125,23 @@ class RouterRouteTest extends PHPUnit_Framework_TestCase
|
|||||||
TestRouter::debug('/my/custom-path', 'get');
|
TestRouter::debug('/my/custom-path', 'get');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testDefaultParameterRegex()
|
||||||
|
{
|
||||||
|
TestRouter::get('/my/{path}', 'DummyController@param', ['defaultParameterRegex' => '[\w\-]+']);
|
||||||
|
$output = TestRouter::debugOutput('/my/custom-regex', 'get');
|
||||||
|
|
||||||
|
$this->assertEquals('custom-regex', $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDefaultParameterRegexGroup()
|
||||||
|
{
|
||||||
|
TestRouter::group(['defaultParameterRegex' => '[\w\-]+'], function() {
|
||||||
|
TestRouter::get('/my/{path}', 'DummyController@param');
|
||||||
|
});
|
||||||
|
|
||||||
|
$output = TestRouter::debugOutput('/my/custom-regex', 'get');
|
||||||
|
|
||||||
|
$this->assertEquals('custom-regex', $output);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user