phoole / route
PHP 的简洁、快速且完全兼容 PSR-7 & PSR-15 路由库
Requires
- php: >=7.2.0
- phoole/base: ^1.0.20
- psr/http-message: ^1.0
- psr/http-server-middleware: ^1.0.1
Requires (Dev)
- guzzlehttp/psr7: 1.*
- phpunit/phpunit: ^8
Provides
README
PHP 的简洁、快速且完全兼容 PSR-7 & PSR-15 路由库。
为什么还需要另一个路由库?
-
超级快速,使用 fastRoute 算法。
-
简洁的路由语法。路由参数和可选路由段。
-
内置 PSR-7 支持。
-
开箱即用的 PSR-15 中间件。
安装
通过 composer
工具安装。
composer require "phoole/route"
或者将以下行添加到您的 composer.json
{ "require": { "phoole/route": "1.*" } }
使用方法
将路由定义(模式、处理程序、默认值等)注入调度器,然后调用 match()
或 process()
。
use Phoole\Route\Router; use GuzzleHttp\Psr7\ServerRequest; use Psr\Http\Message\ServerRequestInterface; $router = (new Router()) ->addGet( '/blog/{action:xd}[/{year:d}[/{month:d}[/{date:d}]]]', function(ServerRequestInterface $request) { $params = $request->getAttribute(Router::URI_PARAMETERS); echo "action is " . $params['action']; } )->addPost( '/blog/post', 'handler2' )->addRoute(new Route( 'GET,HEAD', '/blog/read[/{id:d}]', 'handler3', ['id' => '1'] // default values )); // diaptcher (match & execute controller action) $result = $router->match(new ServerRequest('GET', '/blog/list/2016/05/01')); if ($result->isMatched()) { echo "WOW matched"; }
或者从数组中加载路由,
$routes = [ ['GET', '/user/{action:xd}/{id:d}', 'handler1', ['id' => 1]], [ ... ], ... ]; $router = new Router($routes);
路由语法
-
命名参数
路由模式语法用于指定命名参数或占位符,其中
{foo}
指定名称为foo
的命名参数或占位符,默认正则表达式模式为[^/]++
。为了匹配更具体的类型,您可以指定自定义正则表达式模式,如{foo:[0-9]+}
。// with 'action' & 'id' two named params $dispatcher->addGet('/user/{action:[^0-9/][^/]*}/{id:[0-9]+}', 'handler1');
可以使用以下方式使用预定义的快捷方式作为占位符,
':d}' => ':[0-9]++}', // digit only ':l}' => ':[a-z]++}', // lower case ':u}' => ':[A-Z]++}', // upper case ':a}' => ':[0-9a-zA-Z]++}', // alphanumeric ':c}' => ':[0-9a-zA-Z+_\-\.]++}', // common chars ':nd}' => ':[^0-9/]++}', // not digits ':xd}' => ':[^0-9/][^/]*+}', // no leading digits
前面的模式可以重写为,
// with 'action' & 'id' two named params $router->addGet('/user/{action:xd}/{id:d}', 'handler1');
-
可选段
可以使用
[]
指定路由模式中的可选段,如下所示,// $action, $year/$month/$date are all optional $pattern = '/blog[/{action:xd}][/{year:d}[/{month:d}[/{date:d}]]]';
其中可选段可以是 嵌套的。与其他库不同,可选段不仅限于模式的末尾,只要它是有效的模式,例如示例中的
[/{action:xd}]
。 -
语法限制
-
参数名称 必须 以字符开头
由于
{2}
在正则表达式中具有特殊含义。参数名称 必须 以字符开头。并且在使用占位符时,在内部或外部使用{}
可能会引起混淆,因此不建议使用。 -
[]
在占位符外表示 可选 段[]
不能作为正则表达式模式的一部分用于占位符外部,如果您确实需要将它们用作正则表达式模式的一部分,请将它们包含在占位符 内部。 -
不允许在占位符内使用捕获组
()
不能在占位符内使用捕获组
()
。例如{user:(root|phoole)}
是无效的。相反,您可以使用{user:root|phoole}
或{user:(?:root|phoole)}
。
-
-
默认值
可以在命名参数末尾添加默认值,形式为
{action:xd=list}
。默认值必须是字母数字字符。例如,// $action, $year/$month/$date are all optional $pattern = '/blog[/{action:xd=list}][/{year:d=2016}[/{month:d=01}[/{date:d=01}]]]'; $router->addGet($pattern, 'handler');
路由
-
相同的路由模式
用户可以定义具有不同 HTTP 方法的相同路由模式。
$router ->addGet('/user/{$id}', 'handler1') ->addPost('/user/{$id}', 'handler2');
处理程序
-
处理程序解析
通常,匹配的路由将返回一个处理程序,如
[ 'ControllerName', 'actionName' ]
。处理程序解析器可用于将此伪处理程序解析为实际的可调用对象。用户可以通过实现
Phoole\Route\Resolver\ResolverInterface
来编写自己的处理程序解析器。
-
此 Fast Route 算法 在
Phoole\Route\Parser\FastRouteParser
类中实现,并在本文中详细解释 "使用正则表达式快速请求路由"。phoole/route
默认使用此算法。 -
关于路由算法的评论
-
你可能认为这并不重要。
如果你在你的应用程序中使用路由库,不同的算法对于一个单一请求可能只相差0.1 - 0.2毫秒,这对于一个应用程序来说似乎没有意义,除非你将其用作独立路由器。
-
如果你只是疯狂地追求速度,请尝试网络路由或服务器路由。
-
测试
$ composer test
依赖关系
- PHP >= 7.2.0
附录
-
基于请求信息,例如请求设备、源IP、请求方法等,服务提供商可能将请求直接导向不同的主机、服务器、应用程序模块或处理器。
-
网络级别路由
常见情况,如基于请求的源IP进行路由,将请求路由到最近的服务器,这在内容分发网络(CDN)中很常见,并且在网络级别完成。
-
Web服务器路由
出于性能考虑,一些简单的路由可以在Web服务器级别完成,例如使用Apache或Nginx配置进行简单路由。
例如,如果你的服务器因维护而宕机,你可以按照以下方式替换
.htaccess
文件,DirectorySlash Off Options -MultiViews DirectoryIndex maintenance.php RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-l RewriteRule ^ maintenance.php [QSA,L]
-
应用程序级别路由
它解决了更多复杂的问题,并且更加灵活。
通常,路由在单个点
index.php
完成。所有请求都被配置为首先由该脚本处理,然后路由到不同的程序。
-