yiisoft/router
Composer 安装命令:
composer require yiisoft/router
包简介
Yii router
关键字:
README 文档
README
Yii Router
The package provides PSR-7 compatible request routing and a PSR-15 middleware ready to be used in an application. Instead of implementing routing from ground up, the package provides an interface for configuring routes and could be used with an adapter package. Currently, the only adapter available is FastRoute.
Features
- URL matching and URL generation supporting HTTP methods, hosts, and defaults.
- Good IDE support for defining routes.
- Route groups with infinite nesting.
- Middleware support for both individual routes and groups.
- Ready to use middleware for route matching.
- Convenient
CurrentRouteservice that holds information about last matched route. - Out of the box CORS middleware support.
Requirements
- PHP 8.1 - 8.5.
Installation
The package could be installed with Composer:
composer require yiisoft/router
Additionally, you will need an adapter such as FastRoute.
Defining routes and URL matching
Common usage of the router looks like the following:
use Yiisoft\Router\CurrentRoute; use Yiisoft\Router\Group; use Yiisoft\Router\Route; use Yiisoft\Router\RouteCollection; use Yiisoft\Router\RouteCollectorInterface; use Yiisoft\Router\UrlMatcherInterface; use Yiisoft\Router\Fastroute\UrlMatcher; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; // Define routes $routes = [ Route::get('/') ->action(static function (ServerRequestInterface $request, RequestHandlerInterface $next) use ($responseFactory) { $response = $responseFactory->createResponse(); $response ->getBody() ->write('You are at homepage.'); return $response; }), Route::get('/test/{id:\w+}') ->action(static function (CurrentRoute $currentRoute, RequestHandlerInterface $next) use ($responseFactory) { $id = $currentRoute->getArgument('id'); $response = $responseFactory->createResponse(); $response ->getBody() ->write('You are at test with argument ' . $id); return $response; }) ]; // Add routes defined to route collector $collector = $container->get(RouteCollectorInterface::class); $collector->addRoute(...$routes); // Initialize URL matcher /** @var UrlMatcherInterface $urlMatcher */ $urlMatcher = new UrlMatcher(new RouteCollection($collector)); // Do the match against $request which is PSR-7 ServerRequestInterface. $result = $urlMatcher->match($request); if (!$result->isSuccess()) { // 404 } // $result->arguments() contains arguments from the match. // Run middleware assigned to a route found. $response = $result->process($request, $notFoundHandler);
Note: Despite
UrlGeneratorInterfaceandUrlMatcherInterfacebeing common for all adapters available, certain features and, especially, pattern syntax may differ. To check usage and configuration details, please refer to specific adapter documentation. All examples in this document are for FastRoute adapter.
Middleware usage
In order to simplify usage in PSR-middleware based application, there is a ready to use middleware provided:
$router = $container->get(Yiisoft\Router\UrlMatcherInterface::class); $responseFactory = $container->get(\Psr\Http\Message\ResponseFactoryInterface::class); $routerMiddleware = new Yiisoft\Router\Middleware\Router($router, $responseFactory, $container); // Add middleware to your middleware handler of choice.
In case of a route match router middleware executes handler middleware attached to the route. If there is no match, next application middleware processes the request.
Routes
Route could match for one or more HTTP methods: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS. There are
corresponding static methods for creating a route for a certain method. If a route is to handle multiple methods at once,
it could be created using methods().
use Yiisoft\Router\Route; Route::delete('/post/{id}') ->name('post-delete') ->action([PostController::class, 'actionDelete']); Route::methods([Method::GET, Method::POST], '/page/add') ->name('page-add') ->action([PageController::class, 'actionAdd']);
If you want to generate a URL based on route and its parameters, give it a name with name(). Check "Creating URLs"
for details.
action() in the above is a primary middleware definition that is invoked last when matching result process()
method is called. How middleware are executed and what middleware formats are accepted is defined by middleware
dispatcher used. See readme of yiisoft/middleware-dispatcher
for middleware examples.
If a route should be applied only to a certain host, it could be defined like the following:
use Yiisoft\Router\Route; Route::get('/special') ->name('special') ->action(SpecialAction::class) ->host('https://www.yiiframework.com');
Defaults for parameters could be provided via defaults() method:
use Yiisoft\Router\Route; Route::get('/api[/v{version}]') ->name('api-index') ->action(ApiAction::class) ->defaults(['version' => 1]);
In the above we specify that if "version" is not obtained from URL during matching then it will be 1.
Besides action, additional middleware to execute before the action itself could be defined:
use Yiisoft\Router\Route; Route::methods([Method::GET, Method::POST], '/page/add') ->middleware(Authentication::class) ->middleware(ExtraHeaders::class) ->action([PostController::class, 'add']) ->name('blog/add');
It is typically used for a certain actions that could be reused for multiple routes such as authentication.
If there is a need to either add middleware to be executed first or remove existing middleware from a route,
prependMiddleware() and disableMiddleware() could be used.
If you combine routes from multiple sources and want last route to have priority over existing ones, mark it as "override":
use Yiisoft\Router\Route; Route::get('/special') ->name('special') ->action(SpecialAction::class) ->override();
Route groups
Routes could be grouped. That is useful for API endpoints and similar cases:
use \Yiisoft\Router\Route; use \Yiisoft\Router\Group; use \Yiisoft\Router\RouteCollectorInterface; // for obtaining router see adapter package of choice readme $collector = $container->get(RouteCollectorInterface::class); $collector->addRoute( Group::create('/api') ->middleware(ApiAuthentication::class) ->host('https://example.com') ->routes( Route::get('/comments'), Group::create('/posts')->routes( Route::get('/list'), ), ) );
A group could have a prefix, such as /api in the above. The prefix is applied for each group's route both when
matching and when generating URLs.
Similar to individual routes, a group could have a set of middleware managed using middleware(), prependMiddleware(),
and disableMiddleware(). These middleware are executed prior to matched route's own middleware and action.
If host is specified, all routes in the group would match only if the host match.
Automatic OPTIONS response and CORS
By default, router responds automatically to OPTIONS requests based on the routes defined:
HTTP/1.1 204 No Content
Allow: GET, HEAD
Generally that is fine unless you need CORS headers. In this case, you can add a middleware for handling it such as tuupola/cors-middleware:
use Yiisoft\Router\Group; use \Tuupola\Middleware\CorsMiddleware; return [ Group::create('/api') ->withCors(CorsMiddleware::class) ->routes( // ... ); ];
Creating URLs
URLs could be created using UrlGeneratorInterface::generate(). Let's assume a route is defined like the following:
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; use Psr\Http\Message\ResponseFactoryInterface; use Yiisoft\Yii\Http\Handler\NotFoundHandler; use Yiisoft\Yii\Runner\Http\SapiEmitter; use Yiisoft\Yii\Runner\Http\ServerRequestFactory; use Yiisoft\Router\CurrentRoute; use Yiisoft\Router\Route; use Yiisoft\Router\RouteCollection; use Yiisoft\Router\RouteCollectorInterface; use Yiisoft\Router\Fastroute\UrlMatcher; $request = $container ->get(ServerRequestFactory::class) ->createFromGlobals(); $responseFactory = $container->get(ResponseFactoryInterface::class); $notFoundHandler = new NotFoundHandler($responseFactory); $collector = $container->get(RouteCollectorInterface::class); $collector->addRoute( Route::get('/test/{id:\w+}') ->action(static function (CurrentRoute $currentRoute, RequestHandlerInterface $next) use ($responseFactory) { $id = $currentRoute->getArgument('id'); $response = $responseFactory->createResponse(); $response ->getBody() ->write('You are at test with argument ' . $id); return $response; }) ->name('test') ); $router = new UrlMatcher(new RouteCollection($collector)); $route = $router->match($request); $response = $route->process($request, $notFoundHandler); $emitter = new SapiEmitter(); $emitter->emit($response, $request->getMethod() === Method::HEAD);
Then that is how URL could be obtained for it:
use Yiisoft\Router\UrlGeneratorInterface; function getUrl(UrlGeneratorInterface $urlGenerator, $parameters = []) { return $urlGenerator->generate('test', $parameters); }
Absolute URL cold be generated using UrlGeneratorInterface::generateAbsolute():
use Yiisoft\Router\UrlGeneratorInterface; function getUrl(UrlGeneratorInterface $urlGenerator, $parameters = []) { return $urlGenerator->generateAbsolute('test', $parameters); }
Also, there is a handy UrlGeneratorInterface::generateFromCurrent() method. It allows generating a URL that is
a modified version of the current URL:
use Yiisoft\Router\UrlGeneratorInterface; function getUrl(UrlGeneratorInterface $urlGenerator, $id) { return $urlGenerator->generateFromCurrent(['id' => 42]); }
In the above, ID will be replaced with 42 and the rest of the parameters will stay the same. That is useful for modifying URLs for filtering and/or sorting.
Obtaining current route information
For such a route:
use \Yiisoft\Router\Route; $routes = [ Route::post('/post/{id:\d+}') ->action([PostController::class, 'actionEdit']), ];
The information could be obtained as follows:
use Psr\Http\Message\ResponseInterface use Psr\Http\Message\UriInterface; use Yiisoft\Router\CurrentRoute; use Yiisoft\Router\Route; final class PostController { public function actionEdit(CurrentRoute $currentRoute): ResponseInterface { $postId = $currentRoute->getArgument('id'); if ($postId === null) { throw new \InvalidArgumentException('Post ID is not specified.'); } // ... } }
In addition to commonly used getArgument() method, the following methods are available:
getArguments()- To obtain all arguments at once.getName()- To get route name.getHost()- To get route host.getPattern()- To get route pattern.getMethods()- To get route methods.getUri()- To get current URI.
Documentation
If you need help or have a question, the Yii Forum is a good place for that. You may also check out other Yii Community Resources.
License
The Yii Router is free software. It is released under the terms of the BSD License.
Please see LICENSE for more information.
Maintained by Yii Software.
Support the project
Follow updates
yiisoft/router 适用场景与选型建议
yiisoft/router 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 350.72k 次下载、GitHub Stars 达 62, 最近一次更新时间为 2019 年 05 月 22 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「web」 「router」 「middleware」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 yiisoft/router 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 yiisoft/router 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 yiisoft/router 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Shoot aims to make providing data to your templates more manageable
Model of a web-based resource
Retrieve a WebResourceInterface instance over HTTP
Router
Slim Framework 3 CSRF protection middleware utilities
PMVC App Action Router
统计信息
- 总下载量: 350.72k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 62
- 点击次数: 17
- 依赖项目数: 72
- 推荐数: 2
其他信息
- 授权协议: BSD-3-Clause
- 更新时间: 2019-05-22