bermudaphp / router
v4.0.1
2024-07-14 18:34 UTC
Requires
- php: ^8.1
- bermudaphp/config: ^1.2
- bermudaphp/psr15factory: ^v2.0.3
- bermudaphp/var-export: ^v1.0
- fig/http-message-util: ^v1.1.4
Requires (Dev)
- phpunit/phpunit: ^10.5
README
composer require bermudaphp/router
使用方法
use Bermuda\Router\Routes; $routes = new Routes; $router = Router::fromDnf($routes); $routes->addRoute( RouteRecord::get('home', '/hello/[name]', static function(string $name): void { echo sprintf('Hello, %s!', $name) }) ); $route = $router->match($_SERVER['REQUEST_URI'], $_SERVER['REQUEST_METHOD']); if (!route) { // route not found logics } call_user_func($route->handler, $route->params['name']);
路由路径生成
echo $router->generate('home', ['name' => 'Jane Doe']); // Output /hello/Jane%20Doe
使用PSR-15
$pipeline = new \Bermuda\Pipeline\Pipeline(); $factory = new \Bermuda\MiddlewareFactory\MiddlewareFactory($container, $responseFactory); class Handler implements RequestHandlerInterface { public function handle(ServerRequestInterface $request): ResponseInterface { return new TextResponse(sprintf('Hello, %s!', $request->getAttribute('name'))) } }; $routes->addRoute( RouteRecord::get('home', '/hello/[name:[a-z]]', Handler::class) ); $pipeline->pipe($factory->make(Bermuda\Router\Middleware\MatchRouteMiddleware::class)); $pipeline->pipe($factory->make(Bermuda\Router\Middleware\DispatchRouteMiddleware::class) ->setFallbackHandler($container->get(Bermuda\Router\Middleware\RouteNotFoundHandler::class))); $response = $pipeline->handle($request); send($response)
获取当前路由数据
class Handler implements RequestHandlerInterface { public function handle(ServerRequestInterface $request): ResponseInterface { $route = $request->getAttribute('Bermuda\Router\Middleware\RouteMiddleware')->route; // MatchedRoute instance } };
路由记录HTTP动词辅助工具
RouteRecord::get(string $name, string $path, mixed $handler): RouteRecord ; RouteRecord::post(string $name, string $path, mixed $handler): RouteRecord ; RouteRecord::patch(string $name, string $path, mixed $handler): RouteRecord ; RouteRecord::put(string $name, string $path, mixed $handler): RouteRecord ; RouteRecord::delete(string $name, string $path, mixed $handler): RouteRecord ; RouteRecord::options(string $name, string $path, mixed $handler): RouteRecord ; RouteRecord::head(string $name, string $path, mixed $handler): RouteRecord ;
设置属性占位符模式
$routes->addRoute(RouteRecord::get('users.get, '/api/v1/users/[id:[a-zA-Z]]', static function(ServerRequestInterface $request): ResponseInterface { return findUser($request->getAttribute('id')); })); alternative: $routes->addRoute(RouteRecord::get('users.get, '/api/v1/users/[id]', static function(ServerRequestInterface $request): ResponseInterface { return findUserById($request->getAttribute('id')); })->withToken('id', '[a-zA-Z]'));
可选属性
$routes->addRoute(RouteRecord::get('users.get, '/api/v1/users/[?id]', static function(ServerRequestInterface $request): ResponseInterface { if (($id = $request->getAttribute('id')) !== null) { return findUserById($id); } return get_all_users(); }));
预定义占位符
id: \d+
any: .*
其他未明确定义且作为字符串传递给路径的占位符将匹配模式 .+
路由分组
$group = $routes->group(name: 'api', prifix: '/api'); // set routes group $group->addRoute(RouteRecord::get('users.get, 'users/[?id]', GetUserHandler::class)); $group->addRoute(RouteRecord::post(user.create, 'users', CreateUserHandler::class)); $group->setMiddleware([GuardMiddleware::class]) // set middleware for all routes in group $group->setTokens(['id' => '[a-zA-Z]']) // set tokens for all routes in group $group = $routes->group('api') // get routes group from name
缓存
一旦所有路由都已注册到路由映射且不再改变。调用 $routes->cache 方法将路由映射缓存到一个PHP文件中。然后使用 Routes::createFromCache('/path/to/cached/routes/filename.php')
方法创建一个带有预载路由的映射实例。
$routes->cache('path/to/cached/routes/file.php'); $routes = Routes::createFromCache('path/to/cached/routes/file.php') $router = Router::fromDnf($routes);
缓存上下文
如果你使用了一个与父上下文绑定的闭包(use构造)作为路由处理器,那么你必须传递一个绑定变量的数组到 Routes::createFromCache
方法。见以下示例
$app = new App; $repository = new UserRepository; $routes->addRoute(RouteRecord::get('user.get', '/users/[id]', static function(ServerRequest $request) use ($app, $repository): ResponseInterface { return $app->respond(200, $repository->findById($request->getAttribute('id'))); })); $routes->cache('path/to/cached/routes/file.php'); $routes = Routes::createFromCache('path/to/cached/routes/file.php', compact('app', 'repository'));
缓存限制
目前,缓存实现不允许使用基于对象实例的对象实例和基于对象实例的回调函数来缓存路由。
基准测试
+---------------------------+-------------------+------------+-----------------+-------+--------------+-------------------+
| benchmark | registered_routes | cache_mode | exec_time | its | memory_usage | memory_peak_usage |
+---------------------------+-------------------+------------+-----------------+-------+--------------+-------------------+
| Benchmark\RouterBenchmark | 1001 | disable | 32.680938005447 | 10000 | 16 MB | 16 MB |
| Benchmark\RouterBenchmark | 1001 | enable | 1.298574924469 | 10000 | 16 MB | 16 MB |
+---------------------------+-------------------+------------+-----------------+-------+--------------+-------------------+