rancoud/router

路由包

3.1.6 2024-09-02 12:22 UTC

README

Packagist PHP Version Support Packagist Version Packagist Downloads Composer dependencies Test workflow Codecov

Router PSR7 和 PSR15

安装

composer require rancoud/router

依赖关系

Http 包: https://github.com/rancoud/Http

如何使用它?

一般情况

// Instantiation
$router = new Router();

// Add routes
$router->get('/posts', function ($request, $next) {
    return (new MessageFactory())->createResponse(200, null, [], 'ok');
});

// Find route
$found = $router->findRoute('GET', '/posts');

// You can use PSR-7 request for finding Route
$found = $router->findRouteRequest(new \Rancoud\Http\Message\ServerRequest('GET', '/posts'));

// Dispatch (response is a PSR7 object \Psr\Http\Message\Response)
$response = $router->dispatch($request);

// Display Response
$response->send();

路由快捷方式

// Methods shortcuts
$router->get('/posts/{id}', function ($request, $next) {});
$router->post('/posts/{id}', function ($request, $next) {});
$router->put('/posts/{id}', function ($request, $next) {});
$router->patch('/posts/{id}', function ($request, $next) {});
$router->delete('/posts/{id}', function ($request, $next) {});
$router->options('/posts/{id}', function ($request, $next) {});

// Any methods
$router->any('/posts/{id}', function ($request, $next) {});

// CRUD method
$router->crud('/posts', function ($request, $next) {});

路由参数

使用模式 {name} 为您的参数命名

$router->get('/posts/{id}', function ($request, $next) {});

约束

使用正则表达式语法为您的约束

// inline for simple case
$router->get('/{id:\d+}', function ($request, $next) {});

// complex
$route = new Route('GET', '/{id}', function ($request, $next) {});
$route->setParametersConstraints(['id' => '\d+']);

当您多次使用相同的正则表达式时,可以设置全局约束

$router->setGlobalParametersConstraints(['lang' => 'en|fr']);

// {lang} will use the global constraints
$router->get('/article/{lang}', function ($request, $next) {});

// {lang} will use the local constraints define by the route
$router->get('/news/{lang}', function ($request, $next) {})->setParametersConstraints(['lang' => 'jp']);

您可以在每个路由上使用可选参数。
如果未提供,则将 {page} 参数替换为值 1

$route = new Route('GET', '/{id}/{page}', function ($request, $next) {});
$route->setOptionalsParameters(['page' => 1]);

中间件

// global middleware for router
$router->addGlobalMiddleware(function ($request, $next) {});

// middleware for only route
$route = new Route('GET', '/{id}', function ($request, $next) {});
$route->addMiddleware(function ($request, $next) {});

// for passing to next middleware
$router->addGlobalMiddleware(function ($request, $next) {
    $next($request);
});

// you can add an instance of Router as a middleware
$subRouter1 = new Router();
$subRouter1->any('/api/books/{id}', function ($req, $next){
    return (new MessageFactory())->createResponse(200, null, [], 'testRouterception books');
});

$subRouter2 = new Router();
$subRouter2->any('/api/peoples/{id}', function ($req, $next){
    return (new MessageFactory())->createResponse(200, null, [], 'testRouterception peoples');
});

$router->addGlobalMiddleware($subRouter1);
$router->addGlobalMiddleware($subRouter2);

路由中的路由中的路由器

// you can add an instance of Router in a Route callback
$subRouter1 = new Router();
$subRouter1->any('/api/books/{id}', function ($req, $next){
    return (new MessageFactory())->createResponse(200, null, [], 'testRouterception books');
});

$subRouter2 = new Router();
$subRouter2->any('/api/peoples/{id}', function ($req, $next){
    return (new MessageFactory())->createResponse(200, null, [], 'testRouterception peoples');
});

$router->any('/api/books/{id}', $subRouter1);
$router->any('/api/peoples/{id}', $subRouter2);

默认 404

// you can set a default 404
$router->setDefault404( static function ($request, $next) {
    return (new \Rancoud\Http\Message\Factory\Factory())->createResponse(404, '')->withBody(Rancoud\Http\Message\Stream::create('404 content'));
});

// it will return false because no Route is matching
$found = $router->findRoute('GET', '/posts');

// response contains the default 404 callback
$response = $router->dispatch($request);

$response->send();

警告:404 和路由器作为中间件

// create new Router with default 404
$subRouter = new Router();
$subRouter->any('/posts/{id:\d+}', function ($req, $next){
   return (new MessageFactory())->createResponse(200, null, [], 'read 1 post');
});
$subRouter->setDefault404( static function ($request, $next) {
    return (new \Rancoud\Http\Message\Factory\Factory())->createResponse(404, '')->withBody(Rancoud\Http\Message\Stream::create('404 content from subRouter'));
});

// you can add a Router as middleware 
$router->any('/posts/{id}', $subRouter);

// it will return true because Router middleware is matching on /posts/{id}
$found = $router->findRoute('GET', '/posts/incorrect');

// response contains the default 404 callback from $subRouter
$response = $router->dispatch($request);

$response->send();

如果您将路由器用作中间件 并且 设置默认 404,那么 findRouteRequestfindRoute 将返回 true
在调用 dispatch 时,它将使用路由器中间件设置的默认 404 回调。

路由器方法

一般命令

添加路由

  • addRoute(route: \Rancoud\Router\Route): void

添加路由快捷方式

  • get(url: string, callback: string|\Closure|\Psr\Http\Server\MiddlewareInterface|\Rancoud\Router\Router): \Rancoud\Router\Route
  • post(url: string, callback: string|\Closure|\Psr\Http\Server\MiddlewareInterface|\Rancoud\Router\Router): \Rancoud\Router\Route
  • put(url: string, callback: string|\Closure|\Psr\Http\Server\MiddlewareInterface|\Rancoud\Router\Router): \Rancoud\Router\Route
  • patch(url: string, callback: string|\Closure|\Psr\Http\Server\MiddlewareInterface|\Rancoud\Router\Router): \Rancoud\Router\Route
  • delete(url: string, callback: string|\Closure|\Psr\Http\Server\MiddlewareInterface|\Rancoud\Router\Router): \Rancoud\Router\Route
  • options(url: string, callback: string|\Closure|\Psr\Http\Server\MiddlewareInterface|\Rancoud\Router\Router): \Rancoud\Router\Route
  • any(url: string, callback: string|\Closure|\Psr\Http\Server\MiddlewareInterface|\Rancoud\Router\Router): void

为 CRUD 系统添加路由

  • crud(prefixPath: string, callback: string|\Closure|\Psr\Http\Server\MiddlewareInterface|\Rancoud\Router\Router): void

它将创建所有这些路由
GET $prefixPath
GET / POST $prefixPath . '/new'
GET / POST / DELETE $prefixPath . '/{id:\d+}'

使用数组设置路由和路由

  • setupRouterAndRoutesWithConfigArray(config: array): void

在此示例中,您可以使用数组设置路由器中间件和路由

$config = [
    'router' => [
        'middlewares' => [
            'global_callback1',
            'global_callback2',
            'global_callback3'
        ],
        'constraints' => [
            'lang' => 'en|fr'
        ],
        'host' => '{service}.domain.{tld}',
        'host_constraint' => [
            'service' => 'api|backoffice|www|m',
            'tld' => 'en|jp'
        ],
        'default_404' => 'callable_404'
    ],
    'routes' => [
        [
            'methods' => ['GET'],
            'url' => '/articles/{id}',
            'callback' => 'route_callback',
            'constraints' => ['id' => '\w+'],
            'middlewares' => ['route_middleware1', 'route_middleware2'],
            'name' => 'route1'
        ],
        [
            'methods' => ['POST'],
            'url' => '/form',
            'callback' => 'callback',
        ],
        [
            'methods' => ['POST'],
            'url' => '/api/form',
            'callback' => 'callback',
            'host' => 'api.domain.{tld}',
            'host_constraint' => [
                'tld' => 'en|jp'
            ]
        ],
        [
            'methods' => ['GET'],
            'url' => '/blog/{page}',
            'callback' => 'callback',
            'optionals_parameters' => [
                'page' => '1'
            ]
        ]
    ]
];

$router = new Router();
$router->setupRouterAndRoutesWithConfigArray($config);

// you can add a Router as a callback
$subRoute = new Router();
$subRoute->setupRouterAndRoutesWithConfigArray($config);
$router->any('/(.*)', $subRoute);

获取路由

  • getRoutes(): \Rancoud\Router\Route[]

查找路由

  • findRoute(method: string, url: string, [host: string = null]): bool
  • findRouteRequest(request: \Psr\Http\Message\ServerRequestInterface): bool
  • getRouteParameters(): array

运行找到的路由

  • dispatch(request: \Psr\Http\Message\ServerRequestInterface): \Psr\Http\Message\Response
  • handle(request: \Psr\Http\Message\ServerRequestInterface): \Psr\Http\Message\Response

dispatch 和 handle 之间的区别在于 dispatch 首先使用。
handle 来自 PSR17,在 Psr\Http\Message\ServerRequestInterface 中,它对中间件很有用。

中间件

  • addGlobalMiddleware(middleware: \Closure|\Psr\Http\Server\MiddlewareInterface|\Rancoud\Router\Router|string): void
  • setGlobalMiddlewares(middlewares: array): void

全局约束

  • setGlobalParametersConstraints(constraints: array): void
  • setGlobalHostConstraints(constraints: array): void

为命名路由生成 URL

  • generateUrl(routeName: string, [routeParameters: array = []]): ?string

主机约束

  • setGlobalHost(host: string): void

默认 404

  • setDefault404(callback: mixed): void

路由构造函数

设置

必需

路由方法

一般命令

获取器/设置器

  • getMethods(): 数组
  • getUrl(): 字符串
  • getName(): 字符串
  • setName(name: 字符串): 无返回值

约束

  • setParametersConstraints(constraints: 数组): 无返回值
  • getParametersConstraints(): 数组
  • compileRegex(globalConstraints: 数组): 字符串
  • setOptionalsParameters(optionalsParameters: 数组): 无返回值
  • getOptionalsParameters(): 数组

回调

  • getCallback(): 混合类型

中间件

  • addMiddleware(middleware: 闭包|\Psr\Http\Server\MiddlewareInterface|\Rancoud\Router\Router|string): 数组
  • getMiddlewares(): 数组

生成 URL

  • generateUrl([routeParameters: 数组 = []]): 字符串

主机

  • getHost(): 可选字符串
  • setHost(host: 字符串, [hostConstraints: 数组 = []]): 无返回值
  • setHostConstraints(constraints: 数组): 无返回值
  • isSameHost(host: 字符串, globalConstraints: 数组 = []): 布尔值
  • getHostParameters(): 数组

如何开发

composer ci 用于 php-cs-fixer 和 phpunit 以及覆盖率
composer lint 用于 php-cs-fixer
composer test 用于 phpunit 和覆盖率