• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

    php-srouter: 非常轻量级的的路由器。速度快,查找速度不受路由数量的影响。支持请求 ...

    原作者: [db:作者] 来自: 网络 收藏 邀请

    开源软件名称:

    php-srouter

    开源软件地址:

    https://gitee.com/inhere/php-srouter

    开源软件介绍:

    php simple router

    LicensePHP VersionLatest Stable VersionBuild StatusCoverage Status

    非常快速且轻量的请求匹配路由器。

    • 无依赖、简洁、速度快、功能完善
    • 轻量级且速度快,查找速度不受路由数量的影响
    • 支持路由组, 支持路由参数定义,以及丰富的自定义路由选项
    • 支持给指定的路由命名,可根据名称拿到注册的路由对象
    • 支持请求方法: GET POST PUT DELETE HEAD OPTIONS ...
    • 支持自动匹配路由到控制器就像 Yii 一样, 请参看配置项 autoRoute (不推荐)
    • 压测对比数据请看路由测试

    多个版本:

    不同的版本有稍微的区别以适应不同的场景

    • Router 通用版本,也是后几个版本的基础类,适用于所有的情况。
    • SRouter 静态类版本。Router 的简单包装,通过静态方法使用(方便小应用快速使用)
    • CachedRouter 继承自Router,支持路由缓存的版本,可以 缓存路由信息到文件
      • 适合php-fpm 环境使用(有缓存将会省去每次的路由收集和解析消耗)
    • PreMatchRouter 继承自Router,预匹配路由器。当应用的静态路由较多时,将拥有更快的匹配速度
      • 适合php-fpm 环境,php-fpm 情形下,实际上我们在收集路由之前,已经知道了路由path和请求动作METHOD
    • ServerRouter 继承自Router,服务器路由。内置支持动态路由临时缓存. 适合 swoole常驻内存应用使用
      • 最近请求过的动态路由将会缓存为一个静态路由信息,下次相同路由将会直接匹配命中

    内置调度器:

    • 支持事件: found notFound execStart execEnd execError. 当触发事件时你可以做一些事情(比如记录日志等)
    • 支持动态获取action名。支持设置方法执行器(actionExecutor),通过方法执行器来自定义调用真实请求方法.
    • 支持通过方法 $router->dispatch($path, $method) 手动调度一个路由
    • 你即使不配置任何东西, 它也能很好的工作

    路由器管理

    RouterManager 当需要在一个项目里处理多个域名下的请求时,方便的根据不同域名配置多个路由器

    EN README

    项目地址

    安装

    • composer 命令
    composer require inhere/sroute
    • composer.json
    {    "require": {        "inhere/sroute": "dev-master"    }}
    • 直接拉取
    git clone https://github.com/inhere/php-srouter.git // github

    压测

    自动生成了1000条路由,每条有9个参数位,分别测试1000次的

    • 第一条路由匹配
    • 最后一条路由匹配
    • 不存在的路由匹配

    详细的测试代码请看仓库 https://github.com/ulue/php-router-benchmark

    • 压测日期 2018.11.19
    • An example route: /9b37eef21e/{arg1}/{arg2}/{arg3}/{arg4}/{arg5}/{arg6}/{arg7}/{arg8}/{arg9}/bda37e9f9b

    Worst-case matching

    This benchmark matches the last route and unknown route. It generates a randomly prefixed and suffixed route in an attempt to thwart any optimization. 1,000 routes each with 9 arguments.

    This benchmark consists of 14 tests. Each test is executed 1,000 times, the results pruned, and then averaged. Values that fall outside of 3 standard deviations of the mean are discarded.

    Test NameResultsTime(ms)+ IntervalChange
    inhere/sroute(Router) - unknown route(1000 routes)9900.002031+0.00087175% slower
    inhere/sroute(SRouter) - unknown route(1000 routes)9940.002895+0.001736150% slower
    inhere/sroute(Router) - last route(1000 routes)9970.005300+0.004141357% slower
    inhere/sroute(SRouter) - last route(1000 routes)9970.006467+0.005308458% slower
    symfony/routing(cached) - unknown route(1000 routes)9760.012777+0.0116181002% slower
    symfony/routing(cached) - last route(1000 routes)9960.013608+0.0124491074% slower
    mindplay/timber - last route(1000 routes)9980.017211+0.0160521385% slower
    FastRoute - unknown route(1000 routes)9910.039429+0.0382703302% slower
    FastRoute(cached) - unknown route(1000 routes)9900.040800+0.0396413420% slower
    FastRoute(cached) - last route(1000 routes)9990.045065+0.0439063788% slower
    FastRoute - last route(1000 routes)9990.064694+0.0635355481% slower
    Pux PHP - unknown route(1000 routes)9780.316016+0.31485727163% slower
    symfony/routing - unknown route(1000 routes)9920.359482+0.35832330912% slower
    symfony/routing - last route(1000 routes)9990.418813+0.41765436031% slower
    Pux PHP - last route(1000 routes)9990.440489+0.43933037901% slower
    Macaw - unknown route(1000 routes)9911.687441+1.686282145475% slower
    Macaw - last route(1000 routes)9991.786542+1.785383154024% slower

    First route matching

    This benchmark tests how quickly each router can match the first route. 1,000 routes each with 9 arguments.

    This benchmark consists of 7 tests. Each test is executed 1,000 times, the results pruned, and then averaged. Values that fall outside of 3 standard deviations of the mean are discarded.

    Test NameResultsTime+ IntervalChange
    nikic/fast-route - first route(1000)9980.002929+0.001571116% slower
    corneltek/pux(php) - first route(1000)9960.002971+0.001613119% slower
    inhere/sroute(Router) - first(1000)9790.006202+0.004844357% slower
    inhere/sroute(SRouter) - first(1000)9990.006627+0.005269388% slower
    symfony/routing(cached) - first route(1000)9850.006858+0.005501405% slower
    symfony/routing - first route(1000)9950.023105+0.0217471601% slower
    nikic/fast-route(cached) - first route(1000)9990.041133+0.0397752929% slower
    Macaw - first route (1000 routes)9991.782017+1.780659131128% slower

    使用说明

    各个版本的方法名和参数都是一样的

    首先, 需要导入类

    use Inhere\Route\Router;$router = new Router();

    快速开始

    创建一个简单的 public/index.php 文件:

    use Inhere\Route\Router;// 需要先加载 autoload 文件require dirname(__DIR__) . '/vendor/autoload.php';$router = new Router();$router->get('/', function() {    echo 'hello';});// 开始调度运行$router->dispatch();

    使用php启动一个测试server: php -S 127.0.0.1:8080 -t ./public

    好了,现在你可以访问 http://127.0.0.1:8080 可以看到输出 hello

    • 不使用 Composer

    如果是直接下载的包代码,可以加载 test/boot.php 文件,也可以加载到 Inhere\Route 命名空间.

    用如下的语句替换上面的 autoload.php 加载语句即可:

    require dirname(__DIR__) . '/test/boot.php';

    添加路由

    // 匹配 GET 请求. 处理器是个闭包 Closure$router->get('/', function() {    echo 'hello';});// 匹配参数 'test/john'$router->get('/test/{name}', function($params) {    echo $params['name']; // 'john'}, [      'name' => '\w+', // 添加参数匹配限制。若不添加对应的限制,将会自动设置为匹配除了'/'外的任何字符]);// 可选参数支持。匹配  'hello' 'hello/john'$router->get('/hello[/{name}]', function() {    echo $params['name'] ?? 'No input'; // 'john'}, [     'name' => '\w+', // 添加参数匹配限制]);// 匹配 POST 请求$router->post('/user/login', function() {    var_dump($_POST);});// 匹配 GET 或者 POST$router->map(['get', 'post'], '/user/login', function() {    var_dump($_GET, $_POST);});// 允许任何请求方法$router->any('/home', function() {    echo 'hello, you request page is /home';});$router->any('/404', function() {    echo "Sorry,This page not found.";});

    使用路由组

    // 路由组$router->group('/user', function ($router) {    $router->get('/', function () {        echo 'hello. you access: /user/';    });    $router->get('/index', function () {        echo 'hello. you access: /user/index';    });});

    使用控制器

    // 使用 控制器$router->get('/', App\Controllers\HomeController::class);$router->get('/index', 'App\Controllers\HomeController@index');

    备用路由处理

    可以注册一个备用路由处理。当没匹配到时,就会使用它

    $router->any('*', 'fallback_handler');

    如果配置了 'ignoreLastSlash' => true, '/index' 等同于 '/index/'

    注意

    可选参数 - 只能是在路由path的最后

    正确的:

    /hello[/{name}]      // match: /hello/tom   /hello/my[/{name}[/{age}]] // match: /my/tom/78  /my/tom

    错误的:

    /my[/{name}]/{age}

    自动匹配路由

    支持根据请求的URI自动匹配路由(就像 yii 一样), 需配置 autoRoute.

        'autoRoute' => 1, // 启用    'controllerNamespace' => 'App\\Controllers', // 控制器类所在命名空间    'controllerSuffix' => 'Controller', // 控制器类后缀

    请参看示例 example 中的使用

    此时请求没有配置路由的 /demo /demo/test。将会自动尝试从 App\\Controllers 命名空间下去查找 DemoController

    查找逻辑是

    • 只有一节的(如/demo),直接定义它为控制器类名进行查找
    • 大于等于两节的默认先认为最后一节是控制器类名,进行查找
    • 若失败,再尝试将倒数第二节认为是控制器名,最后一节是action名

    设置路由配置

    // set config$router->config([    'ignoreLastSlash' => true,        'autoRoute' => 1,    'controllerNamespace' => 'app\\controllers',    'controllerSuffix' => 'Controller',]);

    NOTICE: 必须在添加路由之前调用 $router->config()

    路由匹配

    array public function match($path, $method)
    • $path string 请求的URI path
    • $method string 请求的request method
    • 返回 array 返回匹配结果信息

    示例

    根据请求的 URI path 和 请求 METHOD 查找匹配我们定义的路由信息。

    $path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);$method = $_SERVER['REQUEST_METHOD'];$routeInfo = $router->match($path, $method);

    根据返回的路由信息,我们就可以自由的决定如何调用对应的处理。

    关于返回的数据结构,可以查看 关键方法参考

    路由调度

    如果你不想自己实现路由调度,可以使用内置的路由调度器 Inhere\Route\Dispatcher\Dispatcher

    use Inhere\Route\Dispatcher\Dispatcher;$dispatcher = new Dispatcher([    // default action method name    'defaultAction' => 'index',    'actionPrefix' => '',    'actionSuffix' => 'Action',    'dynamicAction' => true,    // @see Router::$globalParams['act']    'dynamicActionVar' => 'act',]);

    设置事件处理

    // 成功匹配路由$dispatcher->on(Dispatcher::ON_FOUND, function ($uri, $cb) use ($app) {    $app->logger->debug("Matched uri path: $uri, setting callback is: " . is_string($cb) ? $cb : get_class($cb));});// 当匹配失败, 重定向到 '/404'$dispatcher->on('notFound', '/404');// 或者, 当匹配失败, 输出消息...$dispatcher->on('notFound', function ($uri) {    echo "the page $uri not found!";});

    使用控制器方法

    通过@符号连接控制器类和方法名可以指定执行方法。

    $router->get('/', App\Controllers\HomeController::class);$router->get('/index', 'App\Controllers\HomeController@index');$router->get('/about', 'App\Controllers\HomeController@about');

    NOTICE: 若第二个参数仅仅是个 类,将会尝试执行通过 defaultAction 配置的默认方法

    动态匹配控制器方法

    动态匹配控制器方法, 需配置

    'dynamicAction' => true,  // 启用// action 方法名匹配参数名称,符合条件的才会当做action名称// @see Router::$globalParams['act'] 匹配 '[a-zA-Z][\w-]+''dynamicActionVar' => 'act',

    NOTICE: 使用动态匹配控制器方法, 应当使用 any() 添加路由. 即此时不能限定请求方法 REQUEST_METHOD

    // 访问 '/home/test' 将会执行 'App\Controllers\HomeController::test()'$router->any('/home/{act}', App\Controllers\HomeController::class);// 可匹配 '/home', '/home/test' 等$router->any('/home[/{act}]', App\Controllers\HomeController::class);

    NOTICE: 上面两个的区别是 第一个无法匹配 /home

    使用方法执行器

    配置 actionExecutor 为你需要的方法名,例如配置为 'actionExecutor' => 'run',那所有的方法请求都会提交给此方法。会将真实的 action 作为参数传入run($action), 需要你在此方法中调度来执行真正的请求方法。

    NOTICE: 在你需要将路由器整合到自己的框架时很有用

    示例:

    // 访问 '/user', 将会调用 App\Controllers\UserController::run('')$router->get('/user', 'App\Controllers\UserController');// 访问 '/user/profile', 将会调用 App\Controllers\UserController::run('profile')$router->get('/user/profile', 'App\Controllers\UserController');// 同时配置 'actionExecutor' => 'run' 和 'dynamicAction' => true,// 访问 '/user', 将会调用 App\Controllers\UserController::run('')// 访问 '/user/profile', 将会调用 App\Controllers\UserController::run('profile')$router->any('/user[/{name}]', 'App\Controllers\UserController');

    开始路由匹配和调度

    $router->dispatch($dispatcher);

    运行示例

    示例代码在 example 下。

    • 对象版本

    你可以通过 php -S 127.0.0.1:5670 example/object.php 来运行一个测试服务器, 现在你可以访问 http://127.0.0.1:5671

    测试

    phpunit
    • simple benchmark
    php example/benchmark.php

    License

    MIT

    我的其他项目

    inhere/console github git@osc

    功能丰富的命令行应用,命令行工具库

    inhere/php-validate github git@osc

    一个简洁小巧且功能完善的php验证库。仅有几个文件,无依赖。


    鲜花

    握手

    雷人

    路过

    鸡蛋
    该文章已有0人参与评论

    请发表评论

    全部评论

    专题导读
    热门推荐
    阅读排行榜

    扫描微信二维码

    查看手机版网站

    随时了解更新最新资讯

    139-2527-9053

    在线客服(服务时间 9:00~18:00)

    在线QQ客服
    地址:深圳市南山区西丽大学城创智工业园
    电邮:jeky_zhao#qq.com
    移动电话:139-2527-9053

    Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap