Compare commits

...

18 Commits

Author SHA1 Message Date
Simon Sessingø 355ef01d63 Merge pull request #99 from skipperbent/development
Development
2016-04-22 15:38:02 +02:00
Simon Sessingø ba736b47a3 - Removed support from middlewares on each load - this should be implemented in custom Router instead.
- Updated documentation to reflect how to implement Middlewares loaded on each route.
2016-04-22 15:37:27 +02:00
Simon Sessingø d3162b5a2b Merge pull request #98 from skipperbent/development
Development
2016-04-22 14:30:40 +02:00
Simon Sessingø 6ab1200fd5 - Return $item if it's an array in get method in Input class. 2016-04-22 14:29:21 +02:00
Simon Sessingø 67a00c6800 - Optimized Input class.
- Input class now returns array instead of InputItem instance when object is of type array.
- Optimized key behavior in Input class.
- Optimized arrayToParams method in RouterBase class.
- Added getMergableSettings method to RouterGroup to avoid middleware merge; as they will already be loaded.
2016-04-22 12:55:24 +02:00
Simon Sessingø 810b80487d Merge pull request #97 from skipperbent/development
- Added custom ExceptionHandler example to documentation.
2016-04-21 08:30:34 +02:00
Simon Sessingø 1420203149 - Added custom ExceptionHandler example to documentation.
- Fixed reference to request() helper in Input class.
- Changed RouterBase handleException method to support 404-exceptions.
2016-04-21 07:16:29 +02:00
Simon Sessingø 18a9df56ca Merge pull request #96 from skipperbent/development
Development
2016-04-20 08:10:18 +02:00
Simon Sessingø f7af53a9af - Optimized Input class to ensure that InputFile items are always returned as object as they contain no value. 2016-04-19 14:48:26 +02:00
Simon Sessingø 6b8351f1b8 - Input class no longer tries to search for parameter in FILE or POST if it's not a postback. 2016-04-19 02:08:14 +02:00
Simon Sessingø 6e14ded03f Merge pull request #95 from skipperbent/development
Development
2016-04-16 23:23:56 +02:00
Simon Sessingø eb3ddf2bf7 [OPTIMISATION] Optimized get method in Input class to trim value and return default value if empty. 2016-04-16 21:34:22 +02:00
Simon Sessingø 2afe784f47 [BUGFIX] Fixed middlewaresToLoad logic used before any routes loaded in RouterBase. 2016-04-16 13:08:32 +02:00
Simon Sessingø 899081f8d8 Merge pull request #94 from skipperbent/development
Update README.md
2016-04-16 00:01:22 +02:00
Simon Sessingø 94e98ad5f0 Update README.md 2016-04-16 00:01:12 +02:00
Simon Sessingø e7b9206bc9 Merge pull request #93 from skipperbent/development
Development
2016-04-15 23:21:00 +02:00
Simon Sessingø 8f24256434 Merge pull request #92 from skipperbent/feature-input
Removed old input method from Request class.
2016-04-15 23:20:50 +02:00
Simon Sessingø ec355c90b5 Removed old input method from Request class. 2016-04-15 23:20:16 +02:00
5 changed files with 135 additions and 64 deletions
+89 -8
View File
@@ -103,6 +103,37 @@ SimpleRouter::group(['prefix' => 'v1', 'middleware' => '\MyWebsite\Middleware\So
});
```
#### ExceptionHandler example
This is a basic example of an ExceptionHandler implementation:
```php
namespace BB\Handlers;
use Pecee\Http\Request;
use Pecee\SimpleRouter\RouterEntry;
class CustomExceptionHandler implements IExceptionHandler {
public function handleError( Request $request, RouterEntry $router = null, \Exception $error) {
// If the error-code is 404; show another route which contains the page-not-found
if($error->getCode() === 404) {
// Load your custom 404-page view
}
// Output error as json if on api path.
if(stripos($request->getUri(), '/api') !== false) {
response()->json(['error' => $error->getMessage()]);
}
// Otherwise default exception will be thrown by the router.
}
}
``
### Sub-domain routing
Route groups may also be used to route wildcard sub-domains. 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:
@@ -145,20 +176,33 @@ This is a simple example of an integration into a framework.
The framework has it's own ```Router``` class which inherits from the ```SimpleRouter``` class. This allows the framework to add custom functionality.
```php
namespace MyProject;
<?php
<?php
namespace Pecee;
use Pecee\Exception\RouterException;
use Pecee\Handler\ExceptionHandler;
use Pecee\Http\Middleware\IMiddleware;
use Pecee\SimpleRouter\RouterBase;
use Pecee\SimpleRouter\SimpleRouter;
class Router extends SimpleRouter {
protected static $defaultExceptionHandler;
protected static $defaultMiddlewares = array();
public static function start($defaultNamespace = null) {
// Debug information
Debug::getInstance()->add('Router initialised.');
// Load framework specific controllers
static::get('/js-wrap', 'ControllerJs@wrap', ['namespace' => '\Pecee\Controller'])->setAlias('pecee.js.wrap');
static::get('/css-wrap', 'ControllerCss@wrap', ['namespace' => '\Pecee\Controller'])->setAlias('pecee.css.wrap');
static::get('/captcha', 'ControllerCaptcha@show', ['namespace' => '\Pecee\Controller']);
// Load routes.php
$file = $_ENV['base_path'] . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'routes.php';
$file = $_ENV['base_path'] . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'routes.php';
if(file_exists($file)) {
require_once $file;
}
@@ -168,20 +212,57 @@ class Router extends SimpleRouter {
// Handle exceptions
try {
if(count(static::$defaultMiddlewares)) {
/* @var $middleware \Pecee\Http\Middleware\IMiddleware */
foreach(static::$defaultMiddlewares as $middleware) {
$middleware = new $middleware();
if(!($middleware instanceof IMiddleware)) {
throw new RouterException('Middleware must be implement the IMiddleware interface.');
}
$middleware->handle(RouterBase::getInstance()->getRequest());
}
}
parent::start($defaultNamespace);
} catch(\Exception $e) {
if(self::$defaultExceptionHandler !== null) {
$class = new self::$defaultExceptionHandler();
$class->handleError(RouterBase::getInstance()->getRequest(), $route, $e);
$route = RouterBase::getInstance()->getLoadedRoute();
// Otherwise use the fallback default exceptions handler
if(static::$defaultExceptionHandler !== null) {
static::loadExceptionHandler(static::$defaultExceptionHandler, $route, $e);
}
throw $e;
}
}
public static function setDefaultExceptionHandler($handler) {
self::$defaultExceptionHandler = $handler;
protected static function loadExceptionHandler($class, $route, $e) {
$class = new $class();
if(!($class instanceof ExceptionHandler)) {
throw new \ErrorException('Exception handler must be an instance of \Pecee\Handler\ExceptionHandler');
}
$class->handleError(RouterBase::getInstance()->getRequest(), $route, $e);
}
public static function defaultExceptionHandler($handler) {
static::$defaultExceptionHandler = $handler;
}
/**
* Add default middleware that will be loaded before any route
* @param string|array $middlewares
*/
public static function defaultMiddleware($middlewares) {
if(is_array($middlewares)) {
static::$defaultMiddlewares = $middlewares;
} else {
static::$defaultMiddlewares[] = $middlewares;
}
}
}
@@ -384,7 +465,7 @@ Example:
* @return \Pecee\Http\Input\Input
*/
function input() {
return new \Pecee\Http\Input\Input();
return \Pecee\Http\Request::getInstance()->getInput();
}
```
+19 -17
View File
@@ -1,6 +1,8 @@
<?php
namespace Pecee\Http\Input;
use Pecee\Http\Request;
class Input {
/**
@@ -47,24 +49,27 @@ class Input {
}
public function getObject($index, $default = null) {
$key = (strpos($index, '[') > -1) ? substr($index, strpos($index, '[')+1, strpos($index, ']') - strlen($index)) : null;
$index = (strpos($index, '[') > -1) ? substr($index, 0, strpos($index, '[')) : $index;
$element = $this->get->findFirst($index);
if($element !== null) {
return $element;
return ($key !== null) ? $element[$key] : $element;
}
$element = $this->post->findFirst($index);
if(Request::getInstance()->getMethod() !== 'get') {
if($element !== null) {
return $element;
}
$element = $this->post->findFirst($index);
$element = $this->file->findFirst($index);
if ($element !== null) {
return ($key !== null) ? $element[$key] : $element;
}
if($element !== null) {
return $element;
$element = $this->file->findFirst($index);
if ($element !== null) {
return ($key !== null) ? $element[$key] : $element;
}
}
return $default;
@@ -78,18 +83,15 @@ class Input {
*/
public function get($index, $default = null) {
$key = (strpos($index, '[') > -1) ? substr($index, strpos($index, '[')+1, strpos($index, ']') - strlen($index)) : null;
$index = (strpos($index, '[') > -1) ? substr($index, 0, strpos($index, '[')) : $index;
$item = $this->getObject($index);
if($item !== null) {
if (is_array($item->getValue())) {
return ($key !== null && isset($item->getValue()[$key])) ? $item->getValue()[$key] : $item->getValue();
if(is_array($item) || $item instanceof InputFile) {
return $item;
}
return ($item->getValue() === null) ? $default : $item->getValue();
return (trim($item->getValue()) === '') ? $default : $item->getValue();
}
return $default;
@@ -111,7 +113,7 @@ class Input {
$output[$k] = new InputItem($k, $g);
}
$this->get->{$key} = new InputItem($key, $output);
$this->get->{$key} = $output;
}
}
}
@@ -141,7 +143,7 @@ class Input {
$output[$k] = new InputItem($k, $p);
}
$this->post->{strtolower($key)} = new InputItem($key, $output);
$this->post->{strtolower($key)} = $output;
}
}
}
@@ -181,7 +183,7 @@ class Input {
}
}
$this->file->{strtolower($key)} = new InputItem($key, $output);
$this->file->{strtolower($key)} = $output;
}
}
}
+4 -6
View File
@@ -125,13 +125,11 @@ class Request {
}
/**
* Get request input or default value
* @param string $name
* @param string $defaultValue
* @return mixed
* Get input class
* @return Input
*/
public function getInput($name, $defaultValue) {
return (isset($_REQUEST[$name]) ? $_REQUEST[$name] : $defaultValue);
public function getInput() {
return $this->input;
}
public function isFormatAccepted($format) {
+22 -33
View File
@@ -19,7 +19,7 @@ class RouterBase {
protected $defaultNamespace;
protected $bootManagers;
protected $baseCsrfVerifier;
protected $middlewaresToLoad;
protected $exceptionHandlers;
// TODO: clean up - cut some of the methods down to smaller pieces
@@ -29,7 +29,7 @@ class RouterBase {
$this->backStack = array();
$this->controllerUrlMap = array();
$this->bootManagers = array();
$this->middlewaresToLoad = array();
$this->exceptionHandlers = array();
}
public function addRoute(RouterEntry $route) {
@@ -89,9 +89,9 @@ class RouterBase {
$route->renderRoute($this->request);
$mergedSettings = array_merge($settings, $route->getMergeableSettings());
// Load middleware on group if route matches
if($route->getPrefix() !== null && $route->matchRoute($this->request)) {
$this->middlewaresToLoad[] = $route;
// Add exceptionhandler
if($route->matchRoute($this->request) && $route->getExceptionHandler() !== null) {
$this->exceptionHandlers[] = $route->getExceptionHandler();
}
}
@@ -111,13 +111,6 @@ class RouterBase {
$originalUri = $this->request->getUri();
// Load group middlewares
/* @var $middleware RouterEntry */
foreach($this->middlewaresToLoad as $middleware) {
$middleware->loadMiddleware($this->request);
}
// Initialize boot-managers
if(count($this->bootManagers)) {
/* @var $manager RouterBootManager */
@@ -140,14 +133,6 @@ class RouterBase {
$routeNotAllowed = false;
// Make sure routes with longer urls are rendered first
usort($this->controllerUrlMap, function($a, $b) {
if(strlen($a->getUrl()) < strlen($b->getUrl())) {
return 1;
}
return -1;
});
$max = count($this->controllerUrlMap);
/* @var $route RouterEntry */
@@ -187,14 +172,15 @@ class RouterBase {
}
if(!$this->request->loadedRoute) {
throw new RouterException(sprintf('Route not found: %s', $this->request->getUri()), 404);
$this->handleException(new RouterException(sprintf('Route not found: %s', $this->request->getUri()), 404));
}
}
protected function handleException(\Exception $e) {
if($this->request->loadedRoute !== null && $this->request->loadedRoute->exceptionHandler !== null) {
$handler = new $this->request->loadedRoute->exceptionHandler();
if(!($handler instanceof IExceptionHandler)) {
foreach ($this->exceptionHandlers as $handler) {
$handler = new $handler($this->request);
if (!($handler instanceof IExceptionHandler)) {
throw new RouterException('Exception handler must implement the IExceptionHandler interface.');
}
@@ -298,18 +284,22 @@ class RouterBase {
}
public function arrayToParams(array $getParams = null, $includeEmpty = true) {
if (is_array($getParams) && count($getParams) > 0) {
foreach ($getParams as $key => $val) {
if (!empty($val) || $includeEmpty) {
$getParams[$key] = (is_array($val) ? $this->arrayToParams($val, $includeEmpty) : $key . '=' . $val);
}
if(is_array($getParams)) {
if ($includeEmpty === false) {
$getParams = array_filter($getParams, function ($item) {
if (!empty($item)) {
return $item;
}
});
}
return join('&', $getParams);
return http_build_query($getParams);
}
return '';
}
protected function processUrl($route, $method = null, $parameters = null, $getParams = null) {
protected function processUrl(RouterRoute $route, $method = null, $parameters = null, $getParams = null) {
$domain = '';
@@ -381,8 +371,7 @@ class RouterBase {
if($controller === null && $parameters === null) {
$getParams = (is_array($getParams)) ? array_merge($_GET, $getParams) : $_GET;
$url = parse_url(Request::getInstance()->getUri());
$url = $url['path'];
$url = parse_url($this->request->getUri(), PHP_URL_PATH);
if(count($getParams)) {
$url .= '?' . $this->arrayToParams($getParams);
+1
View File
@@ -92,6 +92,7 @@ class RouterGroup extends RouterEntry {
if($this->getNamespace() !== null && isset($settings['namespace'])) {
unset($settings['namespace']);
}
if(is_array($settings)) {
$this->settings = array_merge($this->settings, $settings);
}