mirror of
https://github.com/skipperbent/simple-php-router.git
synced 2026-06-16 02:30:09 +03:00
Callback, faking route and documentation updates
This commit is contained in:
63
README.md
63
README.md
@@ -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.
|
||||
|
||||
## 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
|
||||
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
|
||||
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
|
||||
the `RouterBase` instance. For easy access you can use the shortcut method `\Pecee\SimpleRouter\SimpleRouter::request()`.
|
||||
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.
|
||||
All information about the current route is stored in the ```\Pecee\SimpleRouter\RouterBase``` instance.
|
||||
|
||||
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
|
||||
$route = request()->getLoadedRoute();
|
||||
use Pecee\SimpleRouter;
|
||||
$route = SimpleRouter::router()->getLoadedRoute();
|
||||
|
||||
$route->setCallback('Example\MyCustomClass@hello');
|
||||
|
||||
@@ -372,6 +373,54 @@ $route->setClass('Example\MyCustomClass');
|
||||
$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
|
||||
|
||||
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
|
||||
// Get parameter site_id or default-value 2
|
||||
$value = input()->get('site_id', '2');
|
||||
$siteId = input()->get('site_id', 2);
|
||||
```
|
||||
|
||||
## Sites
|
||||
|
||||
@@ -6,7 +6,7 @@ use Pecee\Http\Request;
|
||||
|
||||
class ApiVerification implements IMiddleware {
|
||||
|
||||
public function handle(Request $request) {
|
||||
public function handle(Request &$request) {
|
||||
|
||||
// Do authentication
|
||||
$request->authenticated = true;
|
||||
|
||||
@@ -6,6 +6,12 @@ use Pecee\SimpleRouter\RouterEntry;
|
||||
|
||||
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\Exception\TokenMismatchException;
|
||||
use Pecee\Http\Request;
|
||||
use Pecee\SimpleRouter\RouterEntry;
|
||||
|
||||
class BaseCsrfVerifier implements IMiddleware {
|
||||
|
||||
@@ -49,11 +50,11 @@ class BaseCsrfVerifier implements IMiddleware {
|
||||
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($token === null) {
|
||||
|
||||
@@ -2,7 +2,15 @@
|
||||
namespace Pecee\Http\Middleware;
|
||||
|
||||
use Pecee\Http\Request;
|
||||
use Pecee\SimpleRouter\RouterEntry;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* The current loaded route
|
||||
* @var RouterRoute|null
|
||||
*/
|
||||
protected $loadedRoute;
|
||||
|
||||
protected $routeChanges;
|
||||
|
||||
public function __construct() {
|
||||
$this->reset();
|
||||
}
|
||||
@@ -83,6 +91,7 @@ class RouterBase {
|
||||
$this->controllerUrlMap = array();
|
||||
$this->bootManagers = 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;
|
||||
|
||||
// Create a fictive request - so it can be changed in the middleware or exceptionhandler later on...
|
||||
$request = clone $this->request;
|
||||
|
||||
try {
|
||||
|
||||
// Initialize boot-managers
|
||||
if(count($this->bootManagers)) {
|
||||
/* @var $manager RouterBootManager */
|
||||
foreach($this->bootManagers as $manager) {
|
||||
$this->request = $manager->boot($this->request);
|
||||
$request = $manager->boot($request);
|
||||
|
||||
if(!($this->request instanceof 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
|
||||
$this->processRoutes($this->routes);
|
||||
if($newRequest === null && $this->csrfVerifier !== null) {
|
||||
|
||||
// Loop through each route-request
|
||||
$this->processRoutes($this->routes);
|
||||
|
||||
if($original === true && $this->csrfVerifier !== null) {
|
||||
// Verify csrf token for request
|
||||
$this->csrfVerifier->handle($this->request);
|
||||
}
|
||||
|
||||
$request = ($newRequest !== null) ? $newRequest : $request;
|
||||
|
||||
/* @var $route RouterEntry */
|
||||
for ($i = 0; $i < count($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;
|
||||
continue;
|
||||
}
|
||||
|
||||
$routeNotAllowed = false;
|
||||
|
||||
$this->request->rewrite_uri = $this->request->getUri();
|
||||
$this->request->setUri($originalUri);
|
||||
$this->loadedRoute = $route;
|
||||
$request = $this->loadedRoute->loadMiddleware($request, $this->loadedRoute);
|
||||
$request = ($request === null) ? $this->request : $request;
|
||||
|
||||
$this->request->loadedRoute = $route;
|
||||
$this->request->loadedRoute->loadMiddleware($this->request);
|
||||
if($request !== null && $request->getUri() !== $this->request->getUri() && !in_array($request->getUri(), $this->routeChanges)) {
|
||||
$this->routeChanges[] = $request->getUri();
|
||||
$this->routeRequest($request);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->request->loadedRoute->renderRoute($this->request);
|
||||
$this->loadedRoute->renderRoute($request);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -234,18 +253,17 @@ class RouterBase {
|
||||
$this->handleException(new RouterException('Route or method not allowed', 403));
|
||||
}
|
||||
|
||||
if(!$this->request->loadedRoute) {
|
||||
$this->handleException(new RouterException(sprintf('Route not found: %s', $this->request->getUri()), 404));
|
||||
if($this->loadedRoute === null) {
|
||||
$this->handleException(new RouterException(sprintf('Route not found: %s', $request->getUri()), 404));
|
||||
}
|
||||
}
|
||||
|
||||
protected function handleException(\Exception $e) {
|
||||
|
||||
$request = null;
|
||||
$request = clone $this->request;
|
||||
|
||||
/* @var $route RouterGroup */
|
||||
foreach ($this->exceptionHandlers as $route) {
|
||||
$route->loadMiddleware($this->request);
|
||||
$handler = $route->getExceptionHandler();
|
||||
$handler = new $handler();
|
||||
|
||||
@@ -253,13 +271,20 @@ class RouterBase {
|
||||
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;
|
||||
@@ -307,14 +332,6 @@ class RouterBase {
|
||||
$this->bootManagers[] = $bootManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the loaded route
|
||||
* @return RouterEntry
|
||||
*/
|
||||
public function getLoadedRoute() {
|
||||
return $this->request->loadedRoute;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
@@ -451,8 +468,8 @@ class RouterBase {
|
||||
return $url;
|
||||
}
|
||||
|
||||
if($controller === null && $this->request->loadedRoute !== null) {
|
||||
return $this->processUrl($this->request->loadedRoute, $this->request->loadedRoute->getMethod(), $parameters, $getParams);
|
||||
if($controller === null && $this->loadedRoute !== null) {
|
||||
return $this->processUrl($this->loadedRoute, $this->loadedRoute->getMethod(), $parameters, $getParams);
|
||||
}
|
||||
|
||||
$c = '';
|
||||
|
||||
@@ -291,7 +291,7 @@ abstract class RouterEntry {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function loadMiddleware(Request $request) {
|
||||
public function loadMiddleware(Request $request, RouterRoute &$route) {
|
||||
if(count($this->getMiddleware())) {
|
||||
foreach($this->getMiddleware() as $middleware) {
|
||||
$middleware = $this->loadClass($middleware);
|
||||
@@ -300,7 +300,7 @@ abstract class RouterEntry {
|
||||
}
|
||||
|
||||
/* @var $class IMiddleware */
|
||||
$middleware->handle($request);
|
||||
$middleware->handle($request, $route);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,8 +113,8 @@ class RouterGroup extends RouterEntry {
|
||||
// Push middleware if multiple
|
||||
if ($this->getMiddleware() !== null && isset($settings['middleware'])) {
|
||||
|
||||
if (!is_array($this->getMiddleware())) {
|
||||
$settings['middleware'] = array($this->getMiddleware(), $settings['middleware']);
|
||||
if (!is_array($settings['middleware'])) {
|
||||
$settings['middleware'] = array_merge($this->getMiddleware(), array($settings['middleware']));
|
||||
} else {
|
||||
$settings['middleware'][] = $this->getMiddleware();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user