From 1540c02d831b08e288dbc2db7dad92db6c3815a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Rosa?= Date: Tue, 18 Jul 2023 10:46:53 +0100 Subject: [PATCH] Add support for named params in route() method - Added the posibility to pass params to route() method so that it is possible to get a route url by name with the named params replaced --- src/Router.php | 50 ++++++++++++++++++++++++++++--------------- tests/routes.test.php | 26 ++++++++++++++++++++++ 2 files changed, 59 insertions(+), 17 deletions(-) diff --git a/src/Router.php b/src/Router.php index 609efa8..231f65b 100644 --- a/src/Router.php +++ b/src/Router.php @@ -10,7 +10,7 @@ * Leaf Router * --------------- * Super simple and powerful routing with Leaf - * + * * @author Michael Darko * @since 1.2.0 * @version 3.0 @@ -83,7 +83,7 @@ public static function mount(string $path, $handler) /** * Alias for mount - * + * * @param string $path The route sub pattern/path to mount the callbacks on * @param callable|array $handler The callback method */ @@ -96,7 +96,7 @@ public static function group(string $path, $handler) /** * Store a route and it's handler - * + * * @param string $methods Allowed HTTP methods (separated by `|`) * @param string $pattern The route pattern/path to match * @param string|array|callable $handler The handler for route when matched @@ -156,7 +156,7 @@ public static function match(string $methods, string $pattern, $handler) /** * Add a route with all available HTTP methods - * + * * @param string $pattern The route pattern/path to match * @param string|array|callable The handler for route when matched */ @@ -171,7 +171,7 @@ public static function all(string $pattern, $handler) /** * Add a route with GET method - * + * * @param string $pattern The route pattern/path to match * @param string|array|callable The handler for route when matched */ @@ -182,7 +182,7 @@ public static function get(string $pattern, $handler) /** * Add a route with POST method - * + * * @param string $pattern The route pattern/path to match * @param string|array|callable The handler for route when matched */ @@ -193,7 +193,7 @@ public static function post(string $pattern, $handler) /** * Add a route with PUT method - * + * * @param string $pattern The route pattern/path to match * @param string|array|callable The handler for route when matched */ @@ -204,7 +204,7 @@ public static function put(string $pattern, $handler) /** * Add a route with PATCH method - * + * * @param string $pattern The route pattern/path to match * @param string|array|callable The handler for route when matched */ @@ -215,7 +215,7 @@ public static function patch(string $pattern, $handler) /** * Add a route with OPTIONS method - * + * * @param string $pattern The route pattern/path to match * @param string|array|callable The handler for route when matched */ @@ -226,7 +226,7 @@ public static function options(string $pattern, $handler) /** * Add a route with DELETE method - * + * * @param string $pattern The route pattern/path to match * @param string|array|callable The handler for route when matched */ @@ -254,7 +254,7 @@ public static function redirect( /** * Create a resource route for using controllers. - * + * * This creates a routes that implement CRUD functionality in a controller * `/posts` creates: * - `/posts` - GET | HEAD - Controller@index @@ -264,7 +264,7 @@ public static function redirect( * - `/posts/{id}/edit` - GET | HEAD - Controller@edit * - `/posts/{id}/edit` - POST | PUT | PATCH - Controller@update * - `/posts/{id}/delete` - POST | DELETE - Controller@destroy - * + * * @param string $pattern The base route to use eg: /post * @param string $controller to handle route eg: PostController */ @@ -281,7 +281,7 @@ public static function resource(string $pattern, string $controller) /** * Create a resource route for using controllers without the create and edit actions. - * + * * This creates a routes that implement CRUD functionality in a controller * `/posts` creates: * - `/posts` - GET | HEAD - Controller@index @@ -289,7 +289,7 @@ public static function resource(string $pattern, string $controller) * - `/posts/{id}` - GET | HEAD - Controller@show * - `/posts/{id}/edit` - POST | PUT | PATCH - Controller@update * - `/posts/{id}/delete` - POST | DELETE - Controller@destroy - * + * * @param string $pattern The base route to use eg: /post * @param string $controller to handle route eg: PostController */ @@ -304,7 +304,7 @@ public static function apiResource(string $pattern, string $controller) /** * Redirect to another route - * + * * @param string|array $route The route to redirect to * @param array|null $data Data to pass to the next route */ @@ -335,15 +335,31 @@ public static function push($route, ?array $data = null) * Get route url by defined route name * * @param string $routeName + * @param array|string|null $params * * @return string */ - public static function route(string $routeName): string + public static function route(string $routeName, $params = null): string { if (!isset(static::$namedRoutes[$routeName])) { trigger_error('Route named ' . $routeName . ' not found'); } - return static::$namedRoutes[$routeName]; + $routePath = static::$namedRoutes[$routeName]; + if ($params) { + if (is_array($params)) { + foreach ($params as $key => $value) { + if (!preg_match('/{('. $key .')}/', $routePath)) { + trigger_error('Param "' . $key . '" not found in route "' . static::$namedRoutes[$routeName] . '"'); + } + $routePath = str_replace('{' . $key . '}', $value, $routePath); + } + } + if (is_string($params)) { + $routePath = preg_replace('/{(.*?)}/', $params, $routePath); + } + } + + return $routePath; } } diff --git a/tests/routes.test.php b/tests/routes.test.php index 3959247..826c083 100644 --- a/tests/routes.test.php +++ b/tests/routes.test.php @@ -118,8 +118,34 @@ class TRoute expect($routeUrl)->toBe('/route/url'); }); +test('route should return url with replaced named params using params as array', function () { + $router = new Router; + $router->match('GET', '/movies/{movieId}/photos/{photoId}', ['handler', 'name' => 'route-name']); + + $routeUrl = $router->route('route-name', ['movieId' => 'my-movie', 'photoId' => 'my-photo']); + + expect($routeUrl)->toBe('/movies/my-movie/photos/my-photo'); +}); + +test('route should return url with replaced named params using params as string', function () { + $router = new Router; + $router->match('GET', '/movies/{movieId}/edit', ['handler', 'name' => 'route-name']); + + $routeUrl = $router->route('route-name', 'my-movie'); + + expect($routeUrl)->toBe('/movies/my-movie/edit'); +}); + test('route should throw exception if no route found for name', function () { $router = new Router; expect(fn() => $router->route('non-existent-route-name'))->toThrow(Exception::class); }); + +test('route should throw error if no named param found for params array', function () { + $router = new Router; + $router->match('GET', '/movies/{movieId}/photos/{photoId}', ['handler', 'name' => 'route-name']); + + expect(fn() => $router->route('route-name', ['movieId' => 'my-movie', 'otherId' => 'my-photo', 'someOtherId' => 'my-music'])) + ->toThrow(Exception::class, 'Param "otherId" not found in route "/movies/{movieId}/photos/{photoId}"'); +});