mirror of
https://github.com/skipperbent/simple-php-router.git
synced 2026-07-01 15:29:58 +00:00
Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2c8e65f25b | |||
| eb93584d85 | |||
| bd5d17b6fb | |||
| 7c0ac390fd | |||
| 3fc81b6492 | |||
| b400b86322 | |||
| 1d338e9aa9 | |||
| 889ceaa37f | |||
| 363338c92f | |||
| 3dd9dba029 | |||
| be277f276f | |||
| f215eaa9cf | |||
| 933f2370fe | |||
| b3f8910cab | |||
| 8557741083 | |||
| c60d7d81c1 | |||
| 637b998f02 | |||
| aca7d3d503 | |||
| 846c9e6584 | |||
| 0df469184c | |||
| 649ed28a91 | |||
| 5cb7086e96 | |||
| a2edc1504c | |||
| d31cda8e70 | |||
| 921f050a31 | |||
| dcbf59b305 | |||
| bc16388613 | |||
| d3ed3a61b5 |
@@ -1,5 +1,5 @@
|
|||||||
# Simple PHP router
|
# Simple PHP router
|
||||||
Simple, fast PHP router that is easy to get integrated and in almost any project. Heavily inspired by the Laravel router.
|
Simple, fast and yet powerful PHP router that is easy to get integrated and in any project. Heavily inspired by the Laravel router.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
Add the latest version pf Simple PHP Router to your ```composer.json```
|
Add the latest version pf Simple PHP Router to your ```composer.json```
|
||||||
@@ -33,7 +33,7 @@ Add the latest version pf Simple PHP Router to your ```composer.json```
|
|||||||
|
|
||||||
- Global Constraints
|
- Global Constraints
|
||||||
- Sub-Domain Routing
|
- Sub-Domain Routing
|
||||||
- Required parameters
|
- Optional parameters
|
||||||
|
|
||||||
## Initialising the router
|
## Initialising the router
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use Pecee\CsrfToken;
|
|||||||
use Pecee\Exception\TokenMismatchException;
|
use Pecee\Exception\TokenMismatchException;
|
||||||
use Pecee\Http\Request;
|
use Pecee\Http\Request;
|
||||||
|
|
||||||
class BaseCsrfVerifier extends Middleware {
|
class BaseCsrfVerifier implements IMiddleware {
|
||||||
|
|
||||||
const POST_KEY = 'csrf-token';
|
const POST_KEY = 'csrf-token';
|
||||||
const HEADER_KEY = 'X-CSRF-TOKEN';
|
const HEADER_KEY = 'X-CSRF-TOKEN';
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
namespace Pecee\Http\Middleware;
|
||||||
|
|
||||||
|
use Pecee\Http\Request;
|
||||||
|
|
||||||
|
interface IMiddleware {
|
||||||
|
public function handle(Request $request);
|
||||||
|
}
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Pecee\Http\Middleware;
|
|
||||||
|
|
||||||
use Pecee\Http\Request;
|
|
||||||
use Pecee\SimpleRouter\RouterEntry;
|
|
||||||
|
|
||||||
abstract class Middleware
|
|
||||||
{
|
|
||||||
abstract function handle(Request $request);
|
|
||||||
}
|
|
||||||
@@ -3,16 +3,31 @@ namespace Pecee\Http;
|
|||||||
|
|
||||||
class Request {
|
class Request {
|
||||||
|
|
||||||
|
protected static $instance;
|
||||||
|
|
||||||
|
protected $data;
|
||||||
protected $uri;
|
protected $uri;
|
||||||
protected $host;
|
protected $host;
|
||||||
protected $method;
|
protected $method;
|
||||||
protected $headers;
|
protected $headers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return new instance
|
||||||
|
* @return static
|
||||||
|
*/
|
||||||
|
public static function getInstance() {
|
||||||
|
if(self::$instance === null) {
|
||||||
|
self::$instance = new static();
|
||||||
|
}
|
||||||
|
return self::$instance;
|
||||||
|
}
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
|
$this->data = array();
|
||||||
$this->host = $_SERVER['HTTP_HOST'];
|
$this->host = $_SERVER['HTTP_HOST'];
|
||||||
$this->uri = $_SERVER['REQUEST_URI'];
|
$this->uri = $_SERVER['REQUEST_URI'];
|
||||||
$this->method = (isset($_POST['_method'])) ? strtolower($_POST['_method']) : strtolower($_SERVER['REQUEST_METHOD']);
|
$this->method = (isset($_POST['_method'])) ? strtolower($_POST['_method']) : strtolower($_SERVER['REQUEST_METHOD']);
|
||||||
$this->headers = getallheaders();
|
$this->headers = array_change_key_case(getallheaders(), CASE_LOWER);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -90,7 +105,7 @@ class Request {
|
|||||||
* @return string|null
|
* @return string|null
|
||||||
*/
|
*/
|
||||||
public function getHeader($name) {
|
public function getHeader($name) {
|
||||||
return (isset($this->headers[$name])) ? $this->headers[$name] : null;
|
return (isset($this->headers[strtolower($name)])) ? $this->headers[strtolower($name)] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -103,4 +118,12 @@ class Request {
|
|||||||
return (isset($_REQUEST[$name]) ? $_REQUEST[$name] : $defaultValue);
|
return (isset($_REQUEST[$name]) ? $_REQUEST[$name] : $defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function __set($name, $value = null) {
|
||||||
|
$this->data[$name] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __get($name) {
|
||||||
|
return isset($this->data[$name]) ? $this->data[$name] : null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -27,7 +27,7 @@ class RouterBase {
|
|||||||
$this->routes = array();
|
$this->routes = array();
|
||||||
$this->backstack = array();
|
$this->backstack = array();
|
||||||
$this->controllerUrlMap = array();
|
$this->controllerUrlMap = array();
|
||||||
$this->request = new Request();
|
$this->request = Request::getInstance();
|
||||||
$this->baseCsrfVerifier = new BaseCsrfVerifier();
|
$this->baseCsrfVerifier = new BaseCsrfVerifier();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,6 +58,7 @@ class RouterBase {
|
|||||||
|
|
||||||
$newPrefixes = $prefixes;
|
$newPrefixes = $prefixes;
|
||||||
$mergedSettings = array_merge($settings, $route->getMergeableSettings());
|
$mergedSettings = array_merge($settings, $route->getMergeableSettings());
|
||||||
|
|
||||||
if($route->getPrefix()) {
|
if($route->getPrefix()) {
|
||||||
array_push($newPrefixes, rtrim($route->getPrefix(), '/'));
|
array_push($newPrefixes, rtrim($route->getPrefix(), '/'));
|
||||||
}
|
}
|
||||||
@@ -116,6 +117,7 @@ class RouterBase {
|
|||||||
$routeNotAllowed = false;
|
$routeNotAllowed = false;
|
||||||
|
|
||||||
$this->loadedRoute = $routeMatch;
|
$this->loadedRoute = $routeMatch;
|
||||||
|
$routeMatch->loadMiddleware($this->request);
|
||||||
$routeMatch->renderRoute($this->request);
|
$routeMatch->renderRoute($this->request);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -252,7 +254,7 @@ class RouterBase {
|
|||||||
throw new \InvalidArgumentException('Invalid type for getParams. Must be array or null');
|
throw new \InvalidArgumentException('Invalid type for getParams. Must be array or null');
|
||||||
}
|
}
|
||||||
|
|
||||||
if($controller === null && $parameters === null) {
|
if($controller === null && $parameters === null && $this->loadedRoute !== null) {
|
||||||
return $this->processUrl($this->loadedRoute, null, $getParams);
|
return $this->processUrl($this->loadedRoute, null, $getParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,7 +308,13 @@ class RouterBase {
|
|||||||
ArrayUtil::append($url, $parameters);
|
ArrayUtil::append($url, $parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
return '/' . join('/', $url);
|
$url = '/' . trim(join('/', $url), '/') . '/';
|
||||||
|
|
||||||
|
if(is_array($getParams)) {
|
||||||
|
$url .= '?' . Url::arrayToParams($getParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $url;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getInstance() {
|
public static function getInstance() {
|
||||||
|
|||||||
@@ -17,6 +17,29 @@ class RouterController extends RouterEntry {
|
|||||||
$this->controller = $controller;
|
$this->controller = $controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function renderRoute(Request $request) {
|
||||||
|
if(is_object($this->getCallback()) && is_callable($this->getCallback())) {
|
||||||
|
|
||||||
|
// When the callback is a function
|
||||||
|
call_user_func_array($this->getCallback(), $this->getParameters());
|
||||||
|
} else {
|
||||||
|
// When the callback is a method
|
||||||
|
$controller = explode('@', $this->getCallback());
|
||||||
|
$className = $this->getNamespace() . '\\' . $controller[0];
|
||||||
|
|
||||||
|
$class = $this->loadClass($className);
|
||||||
|
$method = $request->getMethod() . ucfirst($controller[1]);
|
||||||
|
|
||||||
|
if (!method_exists($class, $method)) {
|
||||||
|
throw new RouterException(sprintf('Method %s does not exist in class %s', $method, $className), 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
call_user_func_array(array($class, $method), $this->getParameters());
|
||||||
|
|
||||||
|
return $class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function matchRoute(Request $request) {
|
public function matchRoute(Request $request) {
|
||||||
$url = parse_url($request->getUri());
|
$url = parse_url($request->getUri());
|
||||||
$url = rtrim($url['path'], '/') . '/';
|
$url = rtrim($url['path'], '/') . '/';
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace Pecee\SimpleRouter;
|
namespace Pecee\SimpleRouter;
|
||||||
|
|
||||||
use Pecee\Http\Middleware\Middleware;
|
use Pecee\Http\Middleware\IMiddleware;
|
||||||
use Pecee\Http\Request;
|
use Pecee\Http\Request;
|
||||||
|
|
||||||
abstract class RouterEntry {
|
abstract class RouterEntry {
|
||||||
@@ -10,26 +10,26 @@ abstract class RouterEntry {
|
|||||||
const REQUEST_TYPE_POST = 'post';
|
const REQUEST_TYPE_POST = 'post';
|
||||||
const REQUEST_TYPE_GET = 'get';
|
const REQUEST_TYPE_GET = 'get';
|
||||||
const REQUEST_TYPE_PUT = 'put';
|
const REQUEST_TYPE_PUT = 'put';
|
||||||
|
const REQUEST_TYPE_PATCH = 'patch';
|
||||||
const REQUEST_TYPE_DELETE = 'delete';
|
const REQUEST_TYPE_DELETE = 'delete';
|
||||||
|
|
||||||
public static $allowedRequestTypes = array(
|
public static $allowedRequestTypes = array(
|
||||||
self::REQUEST_TYPE_DELETE,
|
self::REQUEST_TYPE_DELETE,
|
||||||
self::REQUEST_TYPE_GET,
|
self::REQUEST_TYPE_GET,
|
||||||
self::REQUEST_TYPE_POST,
|
self::REQUEST_TYPE_POST,
|
||||||
self::REQUEST_TYPE_PUT
|
self::REQUEST_TYPE_PUT,
|
||||||
|
self::REQUEST_TYPE_PATCH
|
||||||
);
|
);
|
||||||
|
|
||||||
protected $settings;
|
protected $settings;
|
||||||
protected $callback;
|
protected $callback;
|
||||||
protected $parameters;
|
protected $parameters;
|
||||||
protected $parametersRegex;
|
|
||||||
protected $regexMatch;
|
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$this->settings = array();
|
$this->settings = array();
|
||||||
$this->settings['requestMethods'] = array();
|
$this->settings['requestMethods'] = array();
|
||||||
|
$this->settings['parametersRegex'] = array();
|
||||||
$this->parameters = array();
|
$this->parameters = array();
|
||||||
$this->parametersRegex = array();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -179,9 +179,9 @@ abstract class RouterEntry {
|
|||||||
public function getMergeableSettings() {
|
public function getMergeableSettings() {
|
||||||
$settings = $this->settings;
|
$settings = $this->settings;
|
||||||
|
|
||||||
if(isset($settings['middleware'])) {
|
/*if(isset($settings['middleware'])) {
|
||||||
unset($settings['middleware']);
|
unset($settings['middleware']);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
if(isset($settings['prefix'])) {
|
if(isset($settings['prefix'])) {
|
||||||
unset($settings['prefix']);
|
unset($settings['prefix']);
|
||||||
@@ -208,7 +208,7 @@ abstract class RouterEntry {
|
|||||||
public function setSettings($settings) {
|
public function setSettings($settings) {
|
||||||
$this->settings = $settings;
|
$this->settings = $settings;
|
||||||
|
|
||||||
if($settings['prefix']) {
|
if(isset($settings['prefix'])) {
|
||||||
$this->setPrefix($settings['prefix']);
|
$this->setPrefix($settings['prefix']);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,21 +243,31 @@ abstract class RouterEntry {
|
|||||||
return new $name();
|
return new $name();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function loadMiddleware(Request $request) {
|
public function loadMiddleware(Request $request) {
|
||||||
if($this->getMiddleware()) {
|
if($this->getMiddleware()) {
|
||||||
$middleware = $this->loadClass($this->getMiddleware());
|
if(is_array($this->getMiddleware())) {
|
||||||
if (!($middleware instanceof Middleware)) {
|
foreach($this->getMiddleware() as $middleware) {
|
||||||
throw new RouterException($this->getMiddleware() . ' must be instance of Middleware');
|
$middleware = $this->loadClass($middleware);
|
||||||
}
|
if (!($middleware instanceof IMiddleware)) {
|
||||||
|
throw new RouterException($middleware . ' must be instance of Middleware');
|
||||||
|
}
|
||||||
|
|
||||||
/* @var $class Middleware */
|
/* @var $class Middleware */
|
||||||
$middleware->handle($request);
|
$middleware->handle($request);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$middleware = $this->loadClass($this->getMiddleware());
|
||||||
|
if (!($middleware instanceof IMiddleware)) {
|
||||||
|
throw new RouterException($this->getMiddleware() . ' must be instance of Middleware');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @var $class Middleware */
|
||||||
|
$middleware->handle($request);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function renderRoute(Request $request) {
|
public function renderRoute(Request $request) {
|
||||||
// Load middleware
|
|
||||||
$this->loadMiddleware($request);
|
|
||||||
|
|
||||||
if(is_object($this->getCallback()) && is_callable($this->getCallback())) {
|
if(is_object($this->getCallback()) && is_callable($this->getCallback())) {
|
||||||
|
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ class RouterGroup extends RouterEntry {
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function matchRoute(Request $request) {
|
public function renderRoute(Request $request) {
|
||||||
// Check if request method is allowed
|
// Check if request method is allowed
|
||||||
|
|
||||||
if(strtolower($request->getUri()) == strtolower($this->prefix) || stripos($request->getUri(), $this->prefix) === 0) {
|
if(trim($this->prefix) === '' || strtolower($request->getUri()) == strtolower($this->prefix) || stripos($request->getUri(), $this->prefix) === 0) {
|
||||||
|
|
||||||
$hasAccess = (!$this->method);
|
$hasAccess = (!$this->method);
|
||||||
|
|
||||||
@@ -29,11 +29,15 @@ class RouterGroup extends RouterEntry {
|
|||||||
throw new RouterException('Method not allowed');
|
throw new RouterException('Method not allowed');
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return parent::renderRoute($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
// No match here, move on...
|
// No match here, move on...
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function matchRoute(Request $request) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -20,9 +20,6 @@ class RouterResource extends RouterEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function renderRoute(Request $request) {
|
public function renderRoute(Request $request) {
|
||||||
// Load middleware
|
|
||||||
$this->loadMiddleware($request);
|
|
||||||
|
|
||||||
if(is_object($this->getCallback()) && is_callable($this->getCallback())) {
|
if(is_object($this->getCallback()) && is_callable($this->getCallback())) {
|
||||||
// When the callback is a function
|
// When the callback is a function
|
||||||
call_user_func_array($this->getCallback(), $this->getParameters());
|
call_user_func_array($this->getCallback(), $this->getParameters());
|
||||||
|
|||||||
@@ -44,12 +44,12 @@ class RouterRoute extends RouterEntry {
|
|||||||
|
|
||||||
$route = $this->url;
|
$route = $this->url;
|
||||||
|
|
||||||
$routeMatch = preg_replace('/'.self::PARAMETERS_REGEX_MATCH.'/is', '', $route);
|
$routeMatch = preg_replace('/\/{0,1}'.self::PARAMETERS_REGEX_MATCH.'\/{0,1}/is', '', $route);
|
||||||
|
|
||||||
// Check if url parameter count matches
|
// Check if url parameter count matches
|
||||||
if(stripos($url, $routeMatch) === 0) {
|
if(stripos($url, $routeMatch) === 0) {
|
||||||
|
|
||||||
$matches = (count(explode('/', rtrim($url, '/'))) == count(explode('/', rtrim($route, '/'))));
|
$matches = true;
|
||||||
|
|
||||||
if($this->regexMatch) {
|
if($this->regexMatch) {
|
||||||
$parameters = $this->parseParameters($url, true, $this->regexMatch);
|
$parameters = $this->parseParameters($url, true, $this->regexMatch);
|
||||||
@@ -61,6 +61,8 @@ class RouterRoute extends RouterEntry {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
$matches = (count(explode('/', rtrim($url, '/'))) == count(explode('/', rtrim($route, '/'))));
|
||||||
|
|
||||||
$url = explode('/', $url);
|
$url = explode('/', $url);
|
||||||
$route = explode('/', rtrim($route, '/'));
|
$route = explode('/', rtrim($route, '/'));
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ class SimpleRouter {
|
|||||||
public static function put($url, $callback, array $settings = null) {
|
public static function put($url, $callback, array $settings = null) {
|
||||||
$route = new RouterRoute($url, $callback);
|
$route = new RouterRoute($url, $callback);
|
||||||
$route->addSettings($settings);
|
$route->addSettings($settings);
|
||||||
$route->setRequestMethods(array(RouterRoute::REQUEST_TYPE_PUT));
|
$route->setRequestMethods(array(RouterRoute::REQUEST_TYPE_PUT, RouterRoute::REQUEST_TYPE_PATCH));
|
||||||
|
|
||||||
$router = RouterBase::getInstance();
|
$router = RouterBase::getInstance();
|
||||||
$router->addRoute($route);
|
$router->addRoute($route);
|
||||||
|
|||||||
Reference in New Issue
Block a user