mirror of
https://github.com/skipperbent/simple-php-router.git
synced 2026-06-17 00:37: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)
|
||||
- [Subdomain-routing](#subdomain-routing)
|
||||
- [Route prefixes](#route-prefixes)
|
||||
- [Partial groups](#partial-groups)
|
||||
- [Form Method Spoofing](#form-method-spoofing)
|
||||
- [Accessing The Current Route](#accessing-the-current-route)
|
||||
- [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)
|
||||
- [Adding routes manually](#adding-routes-manually)
|
||||
- [Parameters](#parameters)
|
||||
- [Custom default regex for matching parameters](#custom-default-regex-for-matching-parameters)
|
||||
- [Extending](#extending)
|
||||
|
||||
- [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
|
||||
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:
|
||||
|
||||
@@ -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
|
||||
|
||||
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
|
||||
* @throws \Pecee\SimpleRouter\Exceptions\NotFoundHttpException
|
||||
* @return void
|
||||
* @return string
|
||||
*/
|
||||
public function renderRoute(Request $request);
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ abstract class Route implements IRoute
|
||||
protected $defaultParameterRegex;
|
||||
protected $paramModifiers = '{}';
|
||||
protected $paramOptionalSymbol = '?';
|
||||
protected $urlRegex = '/^%s\/?$/u';
|
||||
protected $group;
|
||||
protected $parent;
|
||||
protected $callback;
|
||||
@@ -69,7 +70,7 @@ abstract class Route implements IRoute
|
||||
$callback = $this->getCallback();
|
||||
|
||||
if ($callback === null) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
/* Render callback function */
|
||||
@@ -154,14 +155,14 @@ abstract class Route implements IRoute
|
||||
$urlRegex = preg_quote($route, '/');
|
||||
}
|
||||
|
||||
if (preg_match('/^' . $urlRegex . '\/?$/u', $url, $matches) > 0) {
|
||||
if (preg_match(sprintf($this->urlRegex, $urlRegex), $url, $matches) > 0) {
|
||||
|
||||
$values = [];
|
||||
|
||||
if (isset($parameters[1]) === true) {
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,11 +150,11 @@ class RouteGroup extends Route implements IGroupRoute
|
||||
$this->setPrefix($values['prefix'] . $this->prefix);
|
||||
}
|
||||
|
||||
if (isset($values['exceptionHandler'])) {
|
||||
if ($merge === false && isset($values['exceptionHandler'])) {
|
||||
$this->setExceptionHandlers((array)$values['exceptionHandler']);
|
||||
}
|
||||
|
||||
if (isset($values['domain'])) {
|
||||
if ($merge === false && isset($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\IGroupRoute;
|
||||
use Pecee\SimpleRouter\Route\ILoadableRoute;
|
||||
use Pecee\SimpleRouter\Route\IPartialGroupRoute;
|
||||
use Pecee\SimpleRouter\Route\IRoute;
|
||||
|
||||
class Router
|
||||
@@ -129,15 +130,27 @@ class Router
|
||||
|
||||
$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 */
|
||||
if ($route instanceof IGroupRoute) {
|
||||
|
||||
$group = $route;
|
||||
|
||||
$this->processingRoute = true;
|
||||
$route->renderRoute($this->request);
|
||||
$this->processingRoute = false;
|
||||
|
||||
if ($route->matchRoute($url, $this->request) === true) {
|
||||
|
||||
/* Add exception handlers */
|
||||
@@ -146,23 +159,20 @@ class Router
|
||||
$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) {
|
||||
@@ -258,9 +268,8 @@ class Router
|
||||
if ($rewriteUrl !== null && $rewriteUrl !== $url) {
|
||||
unset($this->processedRoutes[$i]);
|
||||
$this->processedRoutes = array_values($this->processedRoutes);
|
||||
$this->routeRequest(true);
|
||||
|
||||
return;
|
||||
return $this->routeRequest(true);
|
||||
}
|
||||
|
||||
/* Render route */
|
||||
@@ -268,8 +277,6 @@ class Router
|
||||
$this->request->setLoadedRoute($route);
|
||||
|
||||
return $route->renderRoute($this->request);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -293,12 +300,15 @@ class Router
|
||||
|
||||
$this->handleException(new NotFoundHttpException($message, 404));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Exception $e
|
||||
* @throws HttpException
|
||||
* @throws \Exception
|
||||
* @return string
|
||||
*/
|
||||
protected function handleException(\Exception $e)
|
||||
{
|
||||
@@ -335,9 +345,8 @@ class Router
|
||||
if ($rewriteUrl !== null && $rewriteUrl !== $url) {
|
||||
unset($this->exceptionHandlers[$i]);
|
||||
$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\NotFoundHttpException;
|
||||
use Pecee\SimpleRouter\Route\IRoute;
|
||||
use Pecee\SimpleRouter\Route\RoutePartialGroup;
|
||||
use Pecee\SimpleRouter\Route\RouteController;
|
||||
use Pecee\SimpleRouter\Route\RouteGroup;
|
||||
use Pecee\SimpleRouter\Route\RouteResource;
|
||||
@@ -171,14 +172,41 @@ class SimpleRouter
|
||||
*/
|
||||
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->setCallback($callback);
|
||||
$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) {
|
||||
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);
|
||||
|
||||
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