robier/router

非常快且轻量级的PHP路由器

dev-master 2015-10-22 21:09 UTC

This package is auto-updated.

Last update: 2024-09-13 05:28:41 UTC


README

仍在开发中 :)

为了创建一个快速的路由系统,这个库被构建。它如此之快,以至于缓存会成为负担,结果也不会太好 :)

特性

  • 快速匹配未知路由
  • 匹配第一个和最后一个路由的时间几乎相同
  • 路由可以无名称
  • 支持多个域名且速度不受影响
  • 支持HTTP方法(GET、POST、PUT、PATCH、DELETE、HEAD、OPTIONS)
  • 从指定的路由名称反向生成URL并进行参数检查
  • 编写URL定义的特殊语法
    • 两种类型的模式(固定和组合)
    • 常用模式的简短代码
    • 注册自己的常用模式

安装

此项目需要PHP 5.5或更高版本。通过Composer安装此库非常简单,只需运行命令

composer require robier/router

如何使用

为了使一切正常运行,您需要设置PatternParser对象,因为它们是Domain集合的依赖项。设置好后,您可以注册您的路由。

$pattern = new Pattern();
$pattern->register('urlAlias', '[a-zA-Z0-9-\.äÄöÖüÜß]+', true);

$parser = new Parser($pattern);

$collection = new Domain('localhost.loc', $parser);

$collection->add(Route::get('/[foo]'));
$collection->add(Route::get('/contact'));
$collection->add(Route::get('/about'));
$collection->add(Route::get('/prices'));

// will return MatchedRoute with first route
var_dump($collection->match('/bar', 'GET'));

// will return MatchedRoute with last route
var_dump($collection->match('/prices', 'GET'));

// will return false
var_dump($collection->match('/prices', 'POST'))

还有可能使用多域名功能。

$pattern = new Pattern();
$pattern->register('urlAlias', '[a-zA-Z0-9-\.äÄöÖüÜß]+', true);

$parser = new Parser($pattern);

$main = new Domain('www.localhost.loc', $parser);

$main->add(Route::get('/[foo]'));
$main->add(Route::get('/')->setName('home'));
$main->add(Route::get('/user')->setName('user'));
$main->add(Route::get('/about'));
$main->add(Route::get('/prices'));

$api = new Domain('api.localhost.loc', $parser);
$api->add(Route::get('/')->setName('home'));
$api->add(Route::post('/user/[user_id]')->setName('user'));

$domains = new MultiDomains();
$domains->add('main', $main);
$domains->add('api', $api);


// will match user route in api domain
var_dump($domains->match('/user/asd', 'POST'));

// will match last route in main domain
var_dump($domains->match('/prices', 'GET'));

// will generate user route for domain www.localhost.loc
var_dump($domains->generate('user'));

// will generate user route for domain api.localhost.loc
var_dump($domains->generate('api:user', ['user_id' => 1]));

URL语法

规则

  • 每个参数都必须有一个名称
  • 一个URL定义中不应有重复的参数名称
  • 名称应仅由字母和数字组成
  • 定义了两种类型的模式,组合和严格
    • 组合模式可以用AND和OR逻辑运算符组合
  • 只有最后一个参数是可选的,即右侧有?字符
模式

模式可以根据具体情况和要求以不同的方式定义。有两种类型的模式。任何类型都可以由用户在Pattern对象中定义和注册。所有模式都应放在[]括号内。在这些括号内,您需要添加模式名称,这是必填项。如果模式中只有名称,则我们将匹配任何内容,直到下一个片段分隔符/

/test/[foo:n]{5}/bar
      ----------                pattern definition
       ---                      name (required)
          -                     separator between name and patterns (optional)
           -                    pattern or pattern combination (optional)
             ---                quantifier (optional)

示例

/test/[foo]?                    foo can be anything and it is optional
/test/[foo:*]                   foo is everything until end of url
/test/[foo]/bar                 will match anything until next /
/test/[foo]{5,10}/bar           will match anything that have 5 to 10 characters
/test/[foo]{5,}/bar             will match anything that have min 5 characters
/test/[foo]{,10}/bar            will match anything that have max 10 characters
/test/[foo:sha1]/bar            will match only sha1 string (length 40 and hexadecimal)
/test/[foo:n]{5}/bar            will match only number with 5 digits
/test/[foo:n|au]/bar            will match numbers or string (capital letters), but no both
/test/[foo:n-a]/bar             will match string containing number and letter 
/test/[foo:<\d{5}>]/bar         will match number with 5 digits (regex definition)
/test/[foo:(1|18|foo)]/bar      will match numbers 1 or 18 or string foo

预定义的严格模式

md5  - md5 hash matching (32 characters and hexadecimal)
sha1 - sha1 hash matching (40 characters and hexadecimal)
*    - will match everything until end of URL

预定义的组合模式

n  - numeric (0-9)
a  - alpha (a-zA-Z)
al - alpha lower (a-z)
au - alpha upper (A-Z)
c  - characters (_-)
h  - hexadecimal (a-fA-F0-9)

组合模式支持逻辑运算符OR |和AND -,并且可以组合这些模式。

n-a    - numeric and alpha (0-9a-zA-Z)
c-au-n - characters and alpha upper and numeric (-_A-Z0-9)
n|a    - numeric or alpha (0-9|a-zA-Z)
c|au|n - characters or alpha upper or numeric (-_|A-Z|0-9)
c-a|n  - characters and alpha or numeric (-_a-zA-Z|0-9)

您还可以定义组合模式的量化。它在模式的自己的{}大括号中定义。还有一个特殊的量化符?,它将标记该模式为可选的,并且该问号只能出现在URL定义中的最后一个模式上。

{5}   - exactly 5 characters
{1,5} - between 1 and 5 characters
{,5}  - max 5 characters
{5,}  - min 5 characters
?     - pattern is optional

待办事项

  • 创建更好的异常

基准测试

测试了https://github.com/tyler-sommer/php-router-benchmark

最坏情况的匹配结果,最后和未知路由与1000个路由相比。

最佳情况的匹配结果,第一个路由与1000个路由相比。

为什么这么快?

当我们尝试匹配某个路由,例如/bar/foo/test时,系统会

  1. 尝试将此URL与固定URL进行匹配,其中URL是数组的键,如果找到匹配项,则返回结果,否则继续进行
  2. 尝试在正则表达式URL中匹配此URL。首先,我们将此URL分解为多种变体(如/bar/foo/test/bar/foo/bar/)。然后,我们将尝试检查每个变体,看是否能找到它的固定基础作为数组键。如果我们找到了,我们将在该路由集合内运行正则匹配(多个URL可以有相同的固定前缀)。