diff --git a/src/Router.php b/src/Router.php index fce89e2..69a9e44 100644 --- a/src/Router.php +++ b/src/Router.php @@ -57,6 +57,16 @@ class Router */ protected $groups = []; + /** + * @var array List of error group routes + */ + protected $errorGroupNames = []; + + /** + * @var string Error group of requested page + */ + protected $currentErrorGroupName = '/'; + /** * @var array $patterns Pattern definitions for parameters of Route */ @@ -316,15 +326,7 @@ public function run(): void } if ($foundRoute === false) { - if (!$this->errorCallback) { - $this->errorCallback = function () { - $this->response() - ->setStatusCode(Response::HTTP_NOT_FOUND) - ->sendHeaders(); - return $this->exception('Looks like page not found or something went wrong. Please try again.'); - }; - } - call_user_func($this->errorCallback); + $this->notFoundRoute(); } } @@ -350,6 +352,8 @@ public function group(string $prefix, Closure $callback, array $options = []): b array_push($this->groups, $group); + $this->getErrorGroupNames(); + if (is_object($callback)) { call_user_func_array($callback, [$this]); } @@ -428,13 +432,23 @@ public function controller(string $route, string $controller, array $options = [ /** * Routes error function. * - * @param Closure $callback + * @param $callback + * @param array $options * * @return void */ - public function error(Closure $callback): void + public function error($callback,array $options = []): void { - $this->errorCallback = $callback; + if (isset($options['prefix'])) { + $prefix = $options['prefix']; + $this->errorGroupNames[] = $prefix.'/'; + } else { + $prefix = ''; + foreach ($this->groups as $item) { + $prefix .= $item['route']; + } + } + $this->errorCallback[$prefix.'/'] = $callback; } /** @@ -531,6 +545,44 @@ public function getMiddlewares(): array ]; } + /** + * Gets errors generated under group + * + * @return void + */ + protected function getErrorGroupNames() + { + $group = ''; + foreach ($this->groups as $item) { + $group .= $item['route']; + } + $this->errorGroupNames[] = $group.'/'; + } + + protected function notFoundRoute() + { + foreach ($this->errorGroupNames as $key => $item) { + if (str_starts_with($this->getRequestUri(), $item)) + $groupKey = $key; + } + if (isset($groupKey)) + $this->currentErrorGroupName = $this->errorGroupNames[$groupKey]; + + if (!isset($this->errorCallback[$this->currentErrorGroupName])) { + if (!isset($this->errorCallback['/'])) + $this->errorCallback['/'] = function () { + $this->response() + ->setStatusCode(Response::HTTP_NOT_FOUND) + ->sendHeaders(); + return $this->exception('Looks like page not found or something went wrong. Please try again.'); + }; + $this->currentErrorGroupName = '/'; + } + + $this->response()->setStatusCode(Response::HTTP_NOT_FOUND)->sendHeaders(); + $this->routerCommand()->runRoute($this->errorCallback[$this->currentErrorGroupName]); + } + /** * Detect Routes Middleware; before or after * diff --git a/tests/error-test.php b/tests/error-test.php new file mode 100644 index 0000000..2210d3b --- /dev/null +++ b/tests/error-test.php @@ -0,0 +1,42 @@ +group('/test', function ($router) { + $router->get('/',function () use ($router) { + return 'text page'; + }); + $router->get('/blue',function () { + echo 'blue page'; + }); + $router->group('/testing', function ($rou) { + $rou->get('/',function () { + echo 'testing page'; + }); + $rou->error(function () { + echo 'testing error page'; + }); + }); + + + $router->error(function () { + echo 'test error page'; + }); +}); + +$router->group('/test2', function ($router) { + $router->get('/',function () { + echo 'test2 page'; + }); + $router->get('/yellow',function () { + echo 'yellow page'; + }); + $router->error(function () { + die('test2 error page'); + }); +}); + + +$router->error(function () { + echo 'main error page'; +}); + +$router->error('home@notfound',['prefix' => '/test3']);