mirror of
https://github.com/skipperbent/simple-php-router.git
synced 2026-06-17 08:47:52 +00:00
@@ -43,6 +43,7 @@ If you want a great new feature or experience any issues what-so-ever, please fe
|
|||||||
- [Namespaces](#namespaces)
|
- [Namespaces](#namespaces)
|
||||||
- [Subdomain-routing](#subdomain-routing)
|
- [Subdomain-routing](#subdomain-routing)
|
||||||
- [Route prefixes](#route-prefixes)
|
- [Route prefixes](#route-prefixes)
|
||||||
|
- [Partial groups](#partial-groups)
|
||||||
- [Form Method Spoofing](#form-method-spoofing)
|
- [Form Method Spoofing](#form-method-spoofing)
|
||||||
- [Accessing The Current Route](#accessing-the-current-route)
|
- [Accessing The Current Route](#accessing-the-current-route)
|
||||||
- [Other examples](#other-examples)
|
- [Other examples](#other-examples)
|
||||||
@@ -79,7 +80,6 @@ If you want a great new feature or experience any issues what-so-ever, please fe
|
|||||||
- [Bootmanager: loading routes dynamically](#bootmanager-loading-routes-dynamically)
|
- [Bootmanager: loading routes dynamically](#bootmanager-loading-routes-dynamically)
|
||||||
- [Adding routes manually](#adding-routes-manually)
|
- [Adding routes manually](#adding-routes-manually)
|
||||||
- [Parameters](#parameters)
|
- [Parameters](#parameters)
|
||||||
- [Custom default regex for matching parameters](#custom-default-regex-for-matching-parameters)
|
|
||||||
- [Extending](#extending)
|
- [Extending](#extending)
|
||||||
|
|
||||||
- [Credits](#credits)
|
- [Credits](#credits)
|
||||||
@@ -358,7 +358,7 @@ SimpleRouter::any('foo', function() {
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
We've created a simple method which matches `GET` and `POST` which is most commenly used:
|
We've created a simple method which matches `GET` and `POST` which is most commonly used:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
SimpleRouter::form('foo', function() {
|
SimpleRouter::form('foo', function() {
|
||||||
@@ -542,7 +542,7 @@ SimpleRouter::group(['namespace' => 'Admin'], function () {
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
### Subdomain-routing
|
### Sub domain-routing
|
||||||
|
|
||||||
Route groups may also be used to handle sub-domain routing. Sub-domains may be assigned route parameters just like route URIs, allowing you to capture a portion of the sub-domain for usage in your route or controller. The sub-domain may be specified using the `domain` key on the group attribute array:
|
Route groups may also be used to handle sub-domain routing. Sub-domains may be assigned route parameters just like route URIs, allowing you to capture a portion of the sub-domain for usage in your route or controller. The sub-domain may be specified using the `domain` key on the group attribute array:
|
||||||
|
|
||||||
@@ -566,6 +566,29 @@ SimpleRouter::group(['prefix' => '/admin'], function () {
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Partial groups
|
||||||
|
|
||||||
|
Partial router groups has the same benefits as a normal group, but supports parameters and are only rendered once the url has matched.
|
||||||
|
|
||||||
|
This can be extremely useful in situations, where you only want special routes to be added, when a certain criteria or logic has been met.
|
||||||
|
|
||||||
|
**NOTE:** Use partial groups with caution as routes added within are only rendered and available once the url of the partial-group has matched. This can cause `url()` not to find urls for the routes added within.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
|
||||||
|
```php
|
||||||
|
SimpleRouter::partialGroup('/admin/{applicationId}', function ($applicationId) {
|
||||||
|
|
||||||
|
SimpleRouter::get('/', function($applicationId) {
|
||||||
|
|
||||||
|
// Matches The "/admin/applicationId" URL
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Form Method Spoofing
|
## Form Method Spoofing
|
||||||
|
|
||||||
HTML forms do not support `PUT`, `PATCH` or `DELETE` actions. So, when defining `PUT`, `PATCH` or `DELETE` routes that are called from an HTML form, you will need to add a hidden `_method` field to the form. The value sent with the `_method` field will be used as the HTTP request method:
|
HTML forms do not support `PUT`, `PATCH` or `DELETE` actions. So, when defining `PUT`, `PATCH` or `DELETE` routes that are called from an HTML form, you will need to add a hidden `_method` field to the form. The value sent with the `_method` field will be used as the HTTP request method:
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Pecee\SimpleRouter\Route;
|
||||||
|
|
||||||
|
interface IPartialGroupRoute
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -21,7 +21,7 @@ interface IRoute
|
|||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @throws \Pecee\SimpleRouter\Exceptions\NotFoundHttpException
|
* @throws \Pecee\SimpleRouter\Exceptions\NotFoundHttpException
|
||||||
* @return void
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function renderRoute(Request $request);
|
public function renderRoute(Request $request);
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ abstract class Route implements IRoute
|
|||||||
protected $defaultParameterRegex;
|
protected $defaultParameterRegex;
|
||||||
protected $paramModifiers = '{}';
|
protected $paramModifiers = '{}';
|
||||||
protected $paramOptionalSymbol = '?';
|
protected $paramOptionalSymbol = '?';
|
||||||
|
protected $urlRegex = '/^%s\/?$/u';
|
||||||
protected $group;
|
protected $group;
|
||||||
protected $parent;
|
protected $parent;
|
||||||
protected $callback;
|
protected $callback;
|
||||||
@@ -69,7 +70,7 @@ abstract class Route implements IRoute
|
|||||||
$callback = $this->getCallback();
|
$callback = $this->getCallback();
|
||||||
|
|
||||||
if ($callback === null) {
|
if ($callback === null) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Render callback function */
|
/* Render callback function */
|
||||||
@@ -154,14 +155,14 @@ abstract class Route implements IRoute
|
|||||||
$urlRegex = preg_quote($route, '/');
|
$urlRegex = preg_quote($route, '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preg_match('/^' . $urlRegex . '\/?$/u', $url, $matches) > 0) {
|
if (preg_match(sprintf($this->urlRegex, $urlRegex), $url, $matches) > 0) {
|
||||||
|
|
||||||
$values = [];
|
$values = [];
|
||||||
|
|
||||||
if (isset($parameters[1]) === true) {
|
if (isset($parameters[1]) === true) {
|
||||||
|
|
||||||
/* Only take matched parameters with name */
|
/* Only take matched parameters with name */
|
||||||
foreach ($parameters[1] as $name) {
|
foreach ((array)$parameters[1] as $name) {
|
||||||
$values[$name] = (isset($matches[$name]) && $matches[$name] !== '') ? $matches[$name] : null;
|
$values[$name] = (isset($matches[$name]) && $matches[$name] !== '') ? $matches[$name] : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,11 +150,11 @@ class RouteGroup extends Route implements IGroupRoute
|
|||||||
$this->setPrefix($values['prefix'] . $this->prefix);
|
$this->setPrefix($values['prefix'] . $this->prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($values['exceptionHandler'])) {
|
if ($merge === false && isset($values['exceptionHandler'])) {
|
||||||
$this->setExceptionHandlers((array)$values['exceptionHandler']);
|
$this->setExceptionHandlers((array)$values['exceptionHandler']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($values['domain'])) {
|
if ($merge === false && isset($values['domain'])) {
|
||||||
$this->setDomains((array)$values['domain']);
|
$this->setDomains((array)$values['domain']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Pecee\SimpleRouter\Route;
|
||||||
|
|
||||||
|
use Pecee\Http\Request;
|
||||||
|
|
||||||
|
class RoutePartialGroup extends RouteGroup implements IPartialGroupRoute
|
||||||
|
{
|
||||||
|
protected $urlRegex = '/^%s\/?/u';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method called to check if route matches
|
||||||
|
*
|
||||||
|
* @param string $url
|
||||||
|
* @param Request $request
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function matchRoute($url, Request $request)
|
||||||
|
{
|
||||||
|
if ($this->prefix !== null) {
|
||||||
|
/* Parse parameters from current route */
|
||||||
|
$parameters = $this->parseParameters($this->prefix, $url);
|
||||||
|
|
||||||
|
/* If no custom regular expression or parameters was found on this route, we stop */
|
||||||
|
if ($parameters === null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the parameters */
|
||||||
|
$this->setParameters((array)$parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->matchDomain($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@ use Pecee\SimpleRouter\Exceptions\NotFoundHttpException;
|
|||||||
use Pecee\SimpleRouter\Route\IControllerRoute;
|
use Pecee\SimpleRouter\Route\IControllerRoute;
|
||||||
use Pecee\SimpleRouter\Route\IGroupRoute;
|
use Pecee\SimpleRouter\Route\IGroupRoute;
|
||||||
use Pecee\SimpleRouter\Route\ILoadableRoute;
|
use Pecee\SimpleRouter\Route\ILoadableRoute;
|
||||||
|
use Pecee\SimpleRouter\Route\IPartialGroupRoute;
|
||||||
use Pecee\SimpleRouter\Route\IRoute;
|
use Pecee\SimpleRouter\Route\IRoute;
|
||||||
|
|
||||||
class Router
|
class Router
|
||||||
@@ -129,15 +130,27 @@ class Router
|
|||||||
|
|
||||||
$route = $routes[$i];
|
$route = $routes[$i];
|
||||||
|
|
||||||
|
if ($parent !== null) {
|
||||||
|
|
||||||
|
/* Add the parent route */
|
||||||
|
$route->setParent($parent);
|
||||||
|
|
||||||
|
/* Add/merge parent settings with child */
|
||||||
|
$route->setSettings($parent->toArray(), true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($group !== null) {
|
||||||
|
|
||||||
|
/* Add the parent group */
|
||||||
|
$route->setGroup($group);
|
||||||
|
}
|
||||||
|
|
||||||
/* @var $route IGroupRoute */
|
/* @var $route IGroupRoute */
|
||||||
if ($route instanceof IGroupRoute) {
|
if ($route instanceof IGroupRoute) {
|
||||||
|
|
||||||
$group = $route;
|
$group = $route;
|
||||||
|
|
||||||
$this->processingRoute = true;
|
|
||||||
$route->renderRoute($this->request);
|
|
||||||
$this->processingRoute = false;
|
|
||||||
|
|
||||||
if ($route->matchRoute($url, $this->request) === true) {
|
if ($route->matchRoute($url, $this->request) === true) {
|
||||||
|
|
||||||
/* Add exception handlers */
|
/* Add exception handlers */
|
||||||
@@ -146,23 +159,20 @@ class Router
|
|||||||
$exceptionHandlers += $route->getExceptionHandlers();
|
$exceptionHandlers += $route->getExceptionHandlers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Only render partial group if it matches */
|
||||||
|
if ($route instanceof IPartialGroupRoute) {
|
||||||
|
$this->processingRoute = true;
|
||||||
|
$route->renderRoute($this->request);
|
||||||
|
$this->processingRoute = false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ($group !== null) {
|
|
||||||
|
|
||||||
/* Add the parent group */
|
|
||||||
$route->setGroup($group);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($parent !== null) {
|
|
||||||
|
|
||||||
/* Add the parent route */
|
|
||||||
$route->setParent($parent);
|
|
||||||
|
|
||||||
/* Add/merge parent settings with child */
|
|
||||||
$route->setSettings($parent->toArray(), true);
|
|
||||||
|
|
||||||
|
if (($route instanceof IPartialGroupRoute) === false) {
|
||||||
|
$this->processingRoute = true;
|
||||||
|
$route->renderRoute($this->request);
|
||||||
|
$this->processingRoute = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($route instanceof ILoadableRoute) {
|
if ($route instanceof ILoadableRoute) {
|
||||||
@@ -258,9 +268,8 @@ class Router
|
|||||||
if ($rewriteUrl !== null && $rewriteUrl !== $url) {
|
if ($rewriteUrl !== null && $rewriteUrl !== $url) {
|
||||||
unset($this->processedRoutes[$i]);
|
unset($this->processedRoutes[$i]);
|
||||||
$this->processedRoutes = array_values($this->processedRoutes);
|
$this->processedRoutes = array_values($this->processedRoutes);
|
||||||
$this->routeRequest(true);
|
|
||||||
|
|
||||||
return;
|
return $this->routeRequest(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Render route */
|
/* Render route */
|
||||||
@@ -268,8 +277,6 @@ class Router
|
|||||||
$this->request->setLoadedRoute($route);
|
$this->request->setLoadedRoute($route);
|
||||||
|
|
||||||
return $route->renderRoute($this->request);
|
return $route->renderRoute($this->request);
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,12 +300,15 @@ class Router
|
|||||||
|
|
||||||
$this->handleException(new NotFoundHttpException($message, 404));
|
$this->handleException(new NotFoundHttpException($message, 404));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param \Exception $e
|
* @param \Exception $e
|
||||||
* @throws HttpException
|
* @throws HttpException
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function handleException(\Exception $e)
|
protected function handleException(\Exception $e)
|
||||||
{
|
{
|
||||||
@@ -335,9 +345,8 @@ class Router
|
|||||||
if ($rewriteUrl !== null && $rewriteUrl !== $url) {
|
if ($rewriteUrl !== null && $rewriteUrl !== $url) {
|
||||||
unset($this->exceptionHandlers[$i]);
|
unset($this->exceptionHandlers[$i]);
|
||||||
$this->exceptionHandlers = array_values($this->exceptionHandlers);
|
$this->exceptionHandlers = array_values($this->exceptionHandlers);
|
||||||
$this->routeRequest(true);
|
|
||||||
|
|
||||||
return;
|
return $this->routeRequest(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ 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\IRoute;
|
||||||
|
use Pecee\SimpleRouter\Route\RoutePartialGroup;
|
||||||
use Pecee\SimpleRouter\Route\RouteController;
|
use Pecee\SimpleRouter\Route\RouteController;
|
||||||
use Pecee\SimpleRouter\Route\RouteGroup;
|
use Pecee\SimpleRouter\Route\RouteGroup;
|
||||||
use Pecee\SimpleRouter\Route\RouteResource;
|
use Pecee\SimpleRouter\Route\RouteResource;
|
||||||
@@ -171,14 +172,41 @@ class SimpleRouter
|
|||||||
*/
|
*/
|
||||||
public static function group(array $settings = [], \Closure $callback)
|
public static function group(array $settings = [], \Closure $callback)
|
||||||
{
|
{
|
||||||
|
if (is_callable($callback) === false) {
|
||||||
|
throw new \InvalidArgumentException('Invalid callback provided. Only functions or methods supported');
|
||||||
|
}
|
||||||
|
|
||||||
$group = new RouteGroup();
|
$group = new RouteGroup();
|
||||||
$group->setCallback($callback);
|
$group->setCallback($callback);
|
||||||
$group->setSettings($settings);
|
$group->setSettings($settings);
|
||||||
|
|
||||||
|
static::router()->addRoute($group);
|
||||||
|
|
||||||
|
return $group;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Special group that has the same benefits as group but supports
|
||||||
|
* parameters and which are only rendered when the url matches.
|
||||||
|
*
|
||||||
|
* @param string $url
|
||||||
|
* @param array $settings
|
||||||
|
* @param \Closure $callback
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
* @return RoutePartialGroup
|
||||||
|
*/
|
||||||
|
public static function partialGroup($url, \Closure $callback, array $settings = [])
|
||||||
|
{
|
||||||
if (is_callable($callback) === false) {
|
if (is_callable($callback) === false) {
|
||||||
throw new \InvalidArgumentException('Invalid callback provided. Only functions or methods supported');
|
throw new \InvalidArgumentException('Invalid callback provided. Only functions or methods supported');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$settings['prefix'] = $url;
|
||||||
|
|
||||||
|
$group = new RoutePartialGroup();
|
||||||
|
$group->setSettings($settings);
|
||||||
|
$group->setCallback($callback);
|
||||||
|
|
||||||
static::router()->addRoute($group);
|
static::router()->addRoute($group);
|
||||||
|
|
||||||
return $group;
|
return $group;
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require_once 'Dummy/DummyMiddleware.php';
|
||||||
|
require_once 'Dummy/DummyController.php';
|
||||||
|
require_once 'Dummy/Handler/ExceptionHandler.php';
|
||||||
|
require_once 'Helpers/TestRouter.php';
|
||||||
|
|
||||||
|
class RouterPartialGroupTest extends PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
public function testParameters()
|
||||||
|
{
|
||||||
|
$result1 = null;
|
||||||
|
$result2 = null;
|
||||||
|
|
||||||
|
TestRouter::partialGroup('{param1}/{param2}', function ($param1 = null, $param2 = null) use (&$result1, &$result2) {
|
||||||
|
$result1 = $param1;
|
||||||
|
$result2 = $param2;
|
||||||
|
|
||||||
|
TestRouter::get('/', 'DummyController@method1');
|
||||||
|
});
|
||||||
|
|
||||||
|
TestRouter::debug('/param1/param2', 'get');
|
||||||
|
|
||||||
|
$this->assertEquals('param1', $result1);
|
||||||
|
$this->assertEquals('param2', $result2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user