phoole/route

PHP 的简洁、快速且完全兼容 PSR-7 & PSR-15 路由库

1.1.0 2019-11-19 07:10 UTC

This package is auto-updated.

Last update: 2024-09-19 17:29:02 UTC


README

Build Status Scrutinizer Code Quality Code Climate PHP 7 Latest Stable Version License

PHP 的简洁、快速且完全兼容 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 来编写自己的处理程序解析器。

算法

  • FastRoute 算法

    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完成。所有请求都被配置为首先由该脚本处理,然后路由到不同的程序。