From 4f7f06f72401a99b38f3263351fe48e0c533058f Mon Sep 17 00:00:00 2001 From: bim-g Date: Wed, 5 Apr 2023 15:00:10 +0200 Subject: [PATCH] [ENH] Add middleware support to groupe routing --- composer.json | 7 ++- .../controller/UserController.php | 19 ++++-- {demo => example}/index.php | 20 ++++--- .../middleware/UserValidation.php | 4 +- index.php | 2 +- src/Route.php | 22 ++++--- src/Router.php | 60 +++++++++++++++---- src/Traits/ExceptionTrait.php | 13 ++++ src/{ => Traits}/ExecuteRouteTrait.php | 19 +++--- 9 files changed, 111 insertions(+), 55 deletions(-) rename {demo => example}/controller/UserController.php (56%) rename {demo => example}/index.php (54%) rename {demo => example}/middleware/UserValidation.php (86%) create mode 100644 src/Traits/ExceptionTrait.php rename src/{ => Traits}/ExecuteRouteTrait.php (75%) diff --git a/composer.json b/composer.json index 125760b..6e756a8 100644 --- a/composer.json +++ b/composer.json @@ -6,8 +6,8 @@ "autoload": { "psr-4": { "Wepesi\\Routing\\": "src/", - "Wepesi\\Controller\\": "demo/controller/", - "Wepesi\\Middlleware\\": "demo/middleware/" + "Wepesi\\Controller\\": "example/controller/", + "Wepesi\\Middleware\\": "example/middleware/" } }, "homepage": "https://github.com/bim-g/wepesi-router/issues", @@ -28,6 +28,7 @@ "minimum-stability": "dev", "require": { "php" : ">=7.4", - "ext-json": "*" + "ext-json": "*", + "wepesi/optionsresolver": "dev-master" } } diff --git a/demo/controller/UserController.php b/example/controller/UserController.php similarity index 56% rename from demo/controller/UserController.php rename to example/controller/UserController.php index 0c04e79..a55f3ea 100644 --- a/demo/controller/UserController.php +++ b/example/controller/UserController.php @@ -18,17 +18,24 @@ function __construct(){ ['id' => 3, 'name' => 'cygma'], ]; } - function get_users(){ + public function get_users(){ print_r($this->users); } - - function get_user_detail($id){ - $detail = array_filter($this->users,function($user) use ($id){ - return $user["id"] == (int)$id; + private function filterUserByID(int $id){ + return array_filter($this->users, function ($user) use ($id) { + return $user['id'] == (int)$id; }); + } + public function get_user_detail($id){ + $detail = $this->filterUserByID($id); print_r($detail); } - function delete_user($id){ + + public function userExist(int $id){ + $user = count($this->filterUserByID($id)); + print($user>0?'Exist
'.PHP_EOL:'user not found
'.PHP_EOL); + } + public function delete_user($id){ // $index = array_search($id, array_column($this->users,"id")); $detail = array_filter($this->users, function ($user) use ($id) { return $user['id'] != (int)$id; diff --git a/demo/index.php b/example/index.php similarity index 54% rename from demo/index.php rename to example/index.php index 730f570..c7324d9 100644 --- a/demo/index.php +++ b/example/index.php @@ -1,6 +1,6 @@ group('/users', function () use ($router) { $router->get('/', [userController::class,'get_users']); - $router->get('/:id', [userController::class, 'get_user_detail']) - ->middleware([userValidation::class,'detail_user']); - - $router->group('/admin', function () use ($router) { - $router->get('/delete/:id', 'Wepesi\Controller\UserController#delete_user') - ->middleware([userValidation::class,'detail_user']); + $router->group([ + 'pattern'=>'/group', + 'middleware' => [userValidation::class,'detail_user'] + ],function () use($router){ + $router->get('/:id/detail', [userController::class, 'get_user_detail']) + ->middleware([userController::class, 'userExist']); + $router->get('/:id/delete', 'Wepesi\Controller\UserController#delete_user'); }); }); - +/** + * set custom 404 output + */ $router->set404('**',function(){ header($_SERVER['SERVER_PROTOCOL'] . ' 404 Not Found'); print('Not Found : ' . http_response_code()); exit; }); +// $router->run(); \ No newline at end of file diff --git a/demo/middleware/UserValidation.php b/example/middleware/UserValidation.php similarity index 86% rename from demo/middleware/UserValidation.php rename to example/middleware/UserValidation.php index aaff33b..23ed456 100644 --- a/demo/middleware/UserValidation.php +++ b/example/middleware/UserValidation.php @@ -1,8 +1,6 @@ _path = trim($path, '/'); $this->callable = $callable; $this->_matches = []; $this->_params = []; $this->_get_params = []; - $this->middleware_tab = []; + $this->middleware_tab = $middleware ?? []; $this->middleware_exist = false; } @@ -31,7 +35,7 @@ function __construct(string $path, $callable) * @param string|null $url * @return bool */ - function match(?string $url): bool + public function match(?string $url): bool { $url = trim($url, '/'); $path = preg_replace_callback('#:([\w]+)#', [$this, 'paramMatch'], $this->_path); @@ -52,7 +56,7 @@ function match(?string $url): bool /** * */ - function call() + public function call() { try { if (count($this->middleware_tab) > 0) { @@ -64,7 +68,7 @@ function call() } $this->callControllerMiddleware($this->callable,false,$this->_matches); } catch (\Exception $ex) { - echo $ex->getMessage(); + $this->dumper($ex); } } @@ -86,7 +90,7 @@ private function paramMatch(array $match): string * @param $regex * @return $this */ - function with($param, $regex): Route + public function with($param, $regex): Route { $this->_params[$param] = str_replace('(', '(?:', $regex); return $this; @@ -95,7 +99,7 @@ function with($param, $regex): Route /** * @return array */ - function getmatch(): array + public function getmatch(): array { return $this->_matches; } @@ -104,7 +108,7 @@ function getmatch(): array * @param $params * @return array|string|string[] */ - function getUrl($params) + public function getUrl($params) { $path = $this->_path; foreach ($params as $k => $v) { @@ -117,7 +121,7 @@ function getUrl($params) * @param $middleware * @return $this */ - function middleware($middleware): Route + public function middleware($middleware): Route { $this->middleware_tab[] = $middleware; return $this; diff --git a/src/Router.php b/src/Router.php index e43dfaf..7d6ffda 100644 --- a/src/Router.php +++ b/src/Router.php @@ -2,6 +2,10 @@ namespace Wepesi\Routing; +use Wepesi\Resolver\Option; +use Wepesi\Resolver\OptionsResolver; +use Wepesi\Routing\Traits\ExecuteRouteTrait; + /** * A lightweight and simple object-oriented PHP Router. */ @@ -12,6 +16,7 @@ class Router private array $_nameRoute; private string $baseRoute; private $notFoundCallback; + private array $baseMiddleware; use ExecuteRouteTrait; function __construct() @@ -21,6 +26,7 @@ function __construct() $this->_nameRoute = []; $this->_url = $_SERVER['REQUEST_URI']; $this->notFoundCallback = null; + $this->baseMiddleware = []; } /** @@ -30,7 +36,7 @@ function __construct() * @param string|null $name * @return Route */ - function get(string $path, $callable, ?string $name = null): Route + public function get(string $path, $callable, ?string $name = null): Route { return $this->add($path, $callable, 'GET', $name); } @@ -42,7 +48,7 @@ function get(string $path, $callable, ?string $name = null): Route * @param string|null $name * @return Route */ - function post(string $path, $callable, ?string $name = null): Route + public function post(string $path, $callable, ?string $name = null): Route { return $this->add($path, $callable, 'POST', $name); } @@ -54,7 +60,7 @@ function post(string $path, $callable, ?string $name = null): Route * @param string|null $name * @return Route */ - function delete(string $path, $callable, ?string $name = null): Route + public function delete(string $path, $callable, ?string $name = null): Route { return $this->add($path, $callable, 'DELETE', $name); } @@ -66,23 +72,51 @@ function delete(string $path, $callable, ?string $name = null): Route * @param string|null $name * @return Route */ - function put(string $path, $callable, ?string $name = null): Route + public function put(string $path, $callable, ?string $name = null): Route { return $this->add($path, $callable, 'PUT', $name); } /** - * @param string $base_route + * @param $base_route * @param callable $callable */ - function group(string $base_route, callable $callable): void + public function group($base_route, callable $callable): void { + $pattern = $base_route; + if (is_array($base_route)) { + $resolver = new OptionsResolver([ + (new Option('pattern')), + (new Option('middleware'))] + ); + $option = $resolver->resolve($base_route); + if (!isset($option['pattern']) || !isset($option['middleware'])) { + $this->dumper($option); + } + $pattern = $base_route['pattern'] ?? '/'; + + if (isset($base_route['middleware'])) { + $this->baseMiddleware = $this->validateMiddleware($base_route['middleware']); + } + } + $cur_base_route = $this->baseRoute; - $this->baseRoute .= $base_route; + $this->baseRoute .= $pattern; call_user_func($callable); $this->baseRoute = $cur_base_route; } + /** + * @param $middleware + * @return callable[] + */ + private function validateMiddleware($middleware):array{ + $valid_middleware = $middleware; + if((is_array($middleware) && count($middleware) == 2 && is_string($middleware[0]) && is_string($middleware[1])) || is_callable($middleware)){ + $valid_middleware = [$middleware]; + } + return $valid_middleware; + } /** * @param string $path * @param $callable $callable @@ -95,7 +129,7 @@ private function add(string $path, $callable, string $method, ?string $name = nu $path = $this->baseRoute . '/' . trim($path, '/'); $path = $this->baseRoute ? rtrim($path, '/') : $path; - $route = new Route($path, $callable); + $route = new Route($path, $callable,$this->baseMiddleware); $this->routes[$method][] = $route; if (is_string($callable) && $name == null) { @@ -111,9 +145,9 @@ private function add(string $path, $callable, string $method, ?string $name = nu /** * @param string $name * @param array $params - * @return string + * @return void */ - function url(string $name, array $params = []): string + public function url(string $name, array $params = []) { try { if (!isset($this->_nameRoute[$name])) { @@ -121,7 +155,7 @@ function url(string $name, array $params = []): string } return $this->_nameRoute[$name]->geturl($params); } catch (\Exception $ex) { - return $ex->getMessage(); + $this->dumper($ex); } } /** @@ -158,7 +192,7 @@ protected function trigger404($match = null){ /** * @return void */ - function run() + public function run() { try { if (!isset($this->routes[$_SERVER['REQUEST_METHOD']])) { @@ -177,7 +211,7 @@ function run() $this->trigger404($this->notFoundCallback); } } catch (\Exception $ex) { - echo $ex->getMessage(); + $this->dumper($ex); } } } \ No newline at end of file diff --git a/src/Traits/ExceptionTrait.php b/src/Traits/ExceptionTrait.php new file mode 100644 index 0000000..c051058 --- /dev/null +++ b/src/Traits/ExceptionTrait.php @@ -0,0 +1,13 @@ +'); + print_r($object); + print(''); + exit(0); + } +} \ No newline at end of file diff --git a/src/ExecuteRouteTrait.php b/src/Traits/ExecuteRouteTrait.php similarity index 75% rename from src/ExecuteRouteTrait.php rename to src/Traits/ExecuteRouteTrait.php index 025853a..3f1e922 100644 --- a/src/ExecuteRouteTrait.php +++ b/src/Traits/ExecuteRouteTrait.php @@ -1,9 +1,10 @@ isInstantiable()){ + if(!$reflexion->isInstantiable()){ throw new \Exception("Error : class $class_name is not instantiable"); } $class_object = $reflexion->newInstance(); - if (!method_exists($class_object, $class_method)) { throw new \Exception("method : $class_method does not belong the class : $class_name."); } call_user_func_array([$class_object, $class_method], $matches); - } else { - if (isset($callable) && is_callable($callable, true)) { - call_user_func_array($callable, $matches); - } + + } elseif (isset($callable) && is_callable($callable, true)) { + call_user_func_array($callable, $matches); } - return; } catch (\Exception $ex) { - print('
');
-            print_r($ex);
-            print('
'); - exit(); + $this->dumper($ex); } } } \ No newline at end of file