mirror of
https://github.com/skipperbent/simple-php-router.git
synced 2026-07-11 02:52:15 +00:00
Callback, faking route and documentation updates
This commit is contained in:
@@ -354,15 +354,16 @@ By doing this the route will now load the url ```/article/view/1``` instead of `
|
|||||||
The last thing we need to do, is to add our custom boot-manager to the ```routes.php``` file. You can create as many bootmanagers as you like and easily add them in your ```routes.php``` file.
|
The last thing we need to do, is to add our custom boot-manager to the ```routes.php``` file. You can create as many bootmanagers as you like and easily add them in your ```routes.php``` file.
|
||||||
|
|
||||||
## Easily overwrite route about to be loaded
|
## Easily overwrite route about to be loaded
|
||||||
Sometimes it can be useful to manipulate the route that's about to be loaded, for instance if a user is not authenticated or if an error occurred within your Middleware that requires
|
Sometimes it can be useful to manipulate the route about to be loaded.
|
||||||
some other route to be initialised. Simple PHP Router allows you to easily change the route about to be executed. All information about the current route is stored in
|
simple-php-router allows you to easily change the route about to be executed.
|
||||||
the ```\Pecee\SimpleRouter\Http\Request``` object. All information about the current route is as a ```\Pecee\SimpleRouter\Http\Request``` object which can always be obtained on
|
All information about the current route is stored in the ```\Pecee\SimpleRouter\RouterBase``` instance.
|
||||||
the `RouterBase` instance. For easy access you can use the shortcut method `\Pecee\SimpleRouter\SimpleRouter::request()`.
|
|
||||||
|
For easy access you can use the shortcut method `\Pecee\SimpleRouter\SimpleRouter::router()`.
|
||||||
|
|
||||||
**Note:** Please note that it's only possible to change the route BEFORE any route has initially been loaded, so doing this in your custom ExceptionHandler or Middleware is highly recommended.
|
|
||||||
|
|
||||||
```php
|
```php
|
||||||
$route = request()->getLoadedRoute();
|
use Pecee\SimpleRouter;
|
||||||
|
$route = SimpleRouter::router()->getLoadedRoute();
|
||||||
|
|
||||||
$route->setCallback('Example\MyCustomClass@hello');
|
$route->setCallback('Example\MyCustomClass@hello');
|
||||||
|
|
||||||
@@ -372,6 +373,54 @@ $route->setClass('Example\MyCustomClass');
|
|||||||
$route->setMethod('hello');
|
$route->setMethod('hello');
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
#### Faking new route
|
||||||
|
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 `RouterRoute` object from a `Middleware` or `ExceptionHandler`, for like the examples below.
|
||||||
|
|
||||||
|
The example below will cause the router to re-route the request with the "fake" uri. This does require the `$request` object to be returned,
|
||||||
|
otherwise the `request` object will be ignored by the router.
|
||||||
|
|
||||||
|
```php
|
||||||
|
namespace demo\Middlewares;
|
||||||
|
|
||||||
|
use Pecee\Http\Middleware\IMiddleware;
|
||||||
|
use Pecee\Http\Request;
|
||||||
|
use Pecee\SimpleRouter\RouterEntry;
|
||||||
|
|
||||||
|
class CustomMiddleware implements Middleware {
|
||||||
|
|
||||||
|
public function handle(Request $request, RouterEntry &$route = null) {
|
||||||
|
return $request->setUri('/home');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Changing callback
|
||||||
|
You can also change the callback by modifying the `$route` parameter. This is perfect if you just want to display a view quickly - or change the callback depending
|
||||||
|
on some criteria's for the request.
|
||||||
|
|
||||||
|
The callback below will fire immediately after the `Middleware` or `ExceptionHandler` has been loaded, as they are loaded before the route is rendered.
|
||||||
|
If you wish to change the callback from outside, please have this in mind.
|
||||||
|
|
||||||
|
```php
|
||||||
|
namespace demo\Middlewares;
|
||||||
|
|
||||||
|
use Pecee\Http\Middleware\IMiddleware;
|
||||||
|
use Pecee\Http\Request;
|
||||||
|
use Pecee\SimpleRouter\RouterEntry;
|
||||||
|
|
||||||
|
class CustomMiddleware implements Middleware {
|
||||||
|
|
||||||
|
public function handle(Request $request, RouterEntry &$route = null) {
|
||||||
|
$route->callback('DefaultController@home');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Using the Input class to manage parameters
|
## Using the Input class to manage parameters
|
||||||
|
|
||||||
We've added the `Input` class to easy access parameters from your Controller-classes.
|
We've added the `Input` class to easy access parameters from your Controller-classes.
|
||||||
@@ -425,7 +474,7 @@ Below example requires you to have the helper functions added. Please refer to t
|
|||||||
|
|
||||||
```php
|
```php
|
||||||
// Get parameter site_id or default-value 2
|
// Get parameter site_id or default-value 2
|
||||||
$value = input()->get('site_id', '2');
|
$siteId = input()->get('site_id', 2);
|
||||||
```
|
```
|
||||||
|
|
||||||
## Sites
|
## Sites
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use Pecee\Http\Request;
|
|||||||
|
|
||||||
class ApiVerification implements IMiddleware {
|
class ApiVerification implements IMiddleware {
|
||||||
|
|
||||||
public function handle(Request $request) {
|
public function handle(Request &$request) {
|
||||||
|
|
||||||
// Do authentication
|
// Do authentication
|
||||||
$request->authenticated = true;
|
$request->authenticated = true;
|
||||||
|
|||||||
@@ -6,6 +6,12 @@ use Pecee\SimpleRouter\RouterEntry;
|
|||||||
|
|
||||||
interface IExceptionHandler {
|
interface IExceptionHandler {
|
||||||
|
|
||||||
public function handleError(Request $request, RouterEntry $router = null, \Exception $error);
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param RouterEntry|null $route
|
||||||
|
* @param \Exception $error
|
||||||
|
* @return Request|null
|
||||||
|
*/
|
||||||
|
public function handleError(Request $request, RouterEntry &$route = null, \Exception $error);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,7 @@ namespace Pecee\Http\Middleware;
|
|||||||
use Pecee\CsrfToken;
|
use Pecee\CsrfToken;
|
||||||
use Pecee\Exception\TokenMismatchException;
|
use Pecee\Exception\TokenMismatchException;
|
||||||
use Pecee\Http\Request;
|
use Pecee\Http\Request;
|
||||||
|
use Pecee\SimpleRouter\RouterEntry;
|
||||||
|
|
||||||
class BaseCsrfVerifier implements IMiddleware {
|
class BaseCsrfVerifier implements IMiddleware {
|
||||||
|
|
||||||
@@ -49,11 +50,11 @@ class BaseCsrfVerifier implements IMiddleware {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle(Request $request) {
|
public function handle(Request $request, RouterEntry &$route = null) {
|
||||||
|
|
||||||
if($request->getMethod() != 'get' && !$this->skip($request)) {
|
if($request->getMethod() !== 'get' && !$this->skip($request)) {
|
||||||
|
|
||||||
$token = (isset($_POST[static::POST_KEY])) ? $_POST[static::POST_KEY] : null;
|
$token = $request->getInput()->post->findFirst(static::POST_KEY);
|
||||||
|
|
||||||
// If the token is not posted, check headers for valid x-csrf-token
|
// If the token is not posted, check headers for valid x-csrf-token
|
||||||
if($token === null) {
|
if($token === null) {
|
||||||
|
|||||||
@@ -2,7 +2,15 @@
|
|||||||
namespace Pecee\Http\Middleware;
|
namespace Pecee\Http\Middleware;
|
||||||
|
|
||||||
use Pecee\Http\Request;
|
use Pecee\Http\Request;
|
||||||
|
use Pecee\SimpleRouter\RouterEntry;
|
||||||
|
|
||||||
interface IMiddleware {
|
interface IMiddleware {
|
||||||
public function handle(Request $request);
|
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param RouterEntry|null $route
|
||||||
|
* @return Request|null
|
||||||
|
*/
|
||||||
|
public function handle(Request $request, RouterEntry &$route = null);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -71,6 +71,14 @@ class RouterBase {
|
|||||||
*/
|
*/
|
||||||
protected $exceptionHandlers;
|
protected $exceptionHandlers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current loaded route
|
||||||
|
* @var RouterRoute|null
|
||||||
|
*/
|
||||||
|
protected $loadedRoute;
|
||||||
|
|
||||||
|
protected $routeChanges;
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$this->reset();
|
$this->reset();
|
||||||
}
|
}
|
||||||
@@ -83,6 +91,7 @@ class RouterBase {
|
|||||||
$this->controllerUrlMap = array();
|
$this->controllerUrlMap = array();
|
||||||
$this->bootManagers = array();
|
$this->bootManagers = array();
|
||||||
$this->exceptionHandlers = array();
|
$this->exceptionHandlers = array();
|
||||||
|
$this->routeChanges = array();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -173,18 +182,21 @@ class RouterBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function routeRequest($original = true) {
|
public function routeRequest(Request $newRequest = null) {
|
||||||
|
|
||||||
$originalUri = $this->request->getUri();
|
$this->loadedRoute = null;
|
||||||
$routeNotAllowed = false;
|
$routeNotAllowed = false;
|
||||||
|
|
||||||
|
// Create a fictive request - so it can be changed in the middleware or exceptionhandler later on...
|
||||||
|
$request = clone $this->request;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// Initialize boot-managers
|
// Initialize boot-managers
|
||||||
if(count($this->bootManagers)) {
|
if(count($this->bootManagers)) {
|
||||||
/* @var $manager RouterBootManager */
|
/* @var $manager RouterBootManager */
|
||||||
foreach($this->bootManagers as $manager) {
|
foreach($this->bootManagers as $manager) {
|
||||||
$this->request = $manager->boot($this->request);
|
$request = $manager->boot($request);
|
||||||
|
|
||||||
if(!($this->request instanceof Request)) {
|
if(!($this->request instanceof Request)) {
|
||||||
throw new RouterException('Custom router bootmanager "'. get_class($manager) .'" must return instance of Request.');
|
throw new RouterException('Custom router bootmanager "'. get_class($manager) .'" must return instance of Request.');
|
||||||
@@ -192,35 +204,42 @@ class RouterBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop through each route-request
|
if($newRequest === null && $this->csrfVerifier !== null) {
|
||||||
$this->processRoutes($this->routes);
|
|
||||||
|
// Loop through each route-request
|
||||||
|
$this->processRoutes($this->routes);
|
||||||
|
|
||||||
if($original === true && $this->csrfVerifier !== null) {
|
|
||||||
// Verify csrf token for request
|
// Verify csrf token for request
|
||||||
$this->csrfVerifier->handle($this->request);
|
$this->csrfVerifier->handle($this->request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$request = ($newRequest !== null) ? $newRequest : $request;
|
||||||
|
|
||||||
/* @var $route RouterEntry */
|
/* @var $route RouterEntry */
|
||||||
for ($i = 0; $i < count($this->controllerUrlMap); $i++) {
|
for ($i = 0; $i < count($this->controllerUrlMap); $i++) {
|
||||||
|
|
||||||
$route = $this->controllerUrlMap[$i];
|
$route = $this->controllerUrlMap[$i];
|
||||||
|
|
||||||
if ($route->matchRoute($this->request)) {
|
if ($route->matchRoute($request)) {
|
||||||
|
|
||||||
if (count($route->getRequestMethods()) && !in_array($this->request->getMethod(), $route->getRequestMethods())) {
|
if (count($route->getRequestMethods()) && !in_array($request->getMethod(), $route->getRequestMethods())) {
|
||||||
$routeNotAllowed = true;
|
$routeNotAllowed = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$routeNotAllowed = false;
|
$routeNotAllowed = false;
|
||||||
|
|
||||||
$this->request->rewrite_uri = $this->request->getUri();
|
$this->loadedRoute = $route;
|
||||||
$this->request->setUri($originalUri);
|
$request = $this->loadedRoute->loadMiddleware($request, $this->loadedRoute);
|
||||||
|
$request = ($request === null) ? $this->request : $request;
|
||||||
|
|
||||||
$this->request->loadedRoute = $route;
|
if($request !== null && $request->getUri() !== $this->request->getUri() && !in_array($request->getUri(), $this->routeChanges)) {
|
||||||
$this->request->loadedRoute->loadMiddleware($this->request);
|
$this->routeChanges[] = $request->getUri();
|
||||||
|
$this->routeRequest($request);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$this->request->loadedRoute->renderRoute($this->request);
|
$this->loadedRoute->renderRoute($request);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -234,18 +253,17 @@ class RouterBase {
|
|||||||
$this->handleException(new RouterException('Route or method not allowed', 403));
|
$this->handleException(new RouterException('Route or method not allowed', 403));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!$this->request->loadedRoute) {
|
if($this->loadedRoute === null) {
|
||||||
$this->handleException(new RouterException(sprintf('Route not found: %s', $this->request->getUri()), 404));
|
$this->handleException(new RouterException(sprintf('Route not found: %s', $request->getUri()), 404));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function handleException(\Exception $e) {
|
protected function handleException(\Exception $e) {
|
||||||
|
|
||||||
$request = null;
|
$request = clone $this->request;
|
||||||
|
|
||||||
/* @var $route RouterGroup */
|
/* @var $route RouterGroup */
|
||||||
foreach ($this->exceptionHandlers as $route) {
|
foreach ($this->exceptionHandlers as $route) {
|
||||||
$route->loadMiddleware($this->request);
|
|
||||||
$handler = $route->getExceptionHandler();
|
$handler = $route->getExceptionHandler();
|
||||||
$handler = new $handler();
|
$handler = new $handler();
|
||||||
|
|
||||||
@@ -253,13 +271,20 @@ class RouterBase {
|
|||||||
throw new RouterException('Exception handler must implement the IExceptionHandler interface.');
|
throw new RouterException('Exception handler must implement the IExceptionHandler interface.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$request = $handler->handleError($this->request, $this->request->loadedRoute, $e);
|
$request = $handler->handleError($request, $this->loadedRoute, $e);
|
||||||
}
|
$request = ($request === null) ? $this->request : $request;
|
||||||
|
|
||||||
|
if(!in_array($request->getUri(), $this->routeChanges)) {
|
||||||
|
$this->routeChanges[] = $request->getUri();
|
||||||
|
if($request->getUri() !== $this->request->getUri()) {
|
||||||
|
$this->routeRequest($request);
|
||||||
|
} else {
|
||||||
|
$this->routeChanges[] = $request->getUri();
|
||||||
|
$this->loadedRoute->renderRoute($request);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if($request !== null) {
|
|
||||||
$this->request = $request;
|
|
||||||
$this->routeRequest(false);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw $e;
|
throw $e;
|
||||||
@@ -307,14 +332,6 @@ class RouterBase {
|
|||||||
$this->bootManagers[] = $bootManager;
|
$this->bootManagers[] = $bootManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the loaded route
|
|
||||||
* @return RouterEntry
|
|
||||||
*/
|
|
||||||
public function getLoadedRoute() {
|
|
||||||
return $this->request->loadedRoute;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
@@ -451,8 +468,8 @@ class RouterBase {
|
|||||||
return $url;
|
return $url;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($controller === null && $this->request->loadedRoute !== null) {
|
if($controller === null && $this->loadedRoute !== null) {
|
||||||
return $this->processUrl($this->request->loadedRoute, $this->request->loadedRoute->getMethod(), $parameters, $getParams);
|
return $this->processUrl($this->loadedRoute, $this->loadedRoute->getMethod(), $parameters, $getParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
$c = '';
|
$c = '';
|
||||||
|
|||||||
@@ -291,7 +291,7 @@ abstract class RouterEntry {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function loadMiddleware(Request $request) {
|
public function loadMiddleware(Request $request, RouterRoute &$route) {
|
||||||
if(count($this->getMiddleware())) {
|
if(count($this->getMiddleware())) {
|
||||||
foreach($this->getMiddleware() as $middleware) {
|
foreach($this->getMiddleware() as $middleware) {
|
||||||
$middleware = $this->loadClass($middleware);
|
$middleware = $this->loadClass($middleware);
|
||||||
@@ -300,7 +300,7 @@ abstract class RouterEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* @var $class IMiddleware */
|
/* @var $class IMiddleware */
|
||||||
$middleware->handle($request);
|
$middleware->handle($request, $route);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,8 +113,8 @@ class RouterGroup extends RouterEntry {
|
|||||||
// Push middleware if multiple
|
// Push middleware if multiple
|
||||||
if ($this->getMiddleware() !== null && isset($settings['middleware'])) {
|
if ($this->getMiddleware() !== null && isset($settings['middleware'])) {
|
||||||
|
|
||||||
if (!is_array($this->getMiddleware())) {
|
if (!is_array($settings['middleware'])) {
|
||||||
$settings['middleware'] = array($this->getMiddleware(), $settings['middleware']);
|
$settings['middleware'] = array_merge($this->getMiddleware(), array($settings['middleware']));
|
||||||
} else {
|
} else {
|
||||||
$settings['middleware'][] = $this->getMiddleware();
|
$settings['middleware'][] = $this->getMiddleware();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user