我目前正在为一个基于PHP的大型网站制作请求路由器,但是我在尝试为我的路由使用自定义的表达形式时遇到了困难。
虽然我知道有预先制作的替代品和路由器可以让我的生活更轻松,并且具有相同的功能(事实上,我一直在查看它们的源代码以尝试解决这个问题),但我仍然是一个编程学生,学习如何创建自己的路由器只能是一件好事!
例子:
下面是我的一个route表达式的例子:
-
<protocol (https?)>://<wildcard>.example.com/<controller>/{<lang=en (en|de|pl)>/}<name ([a-zA-Z0-9_-]{8})>
这可以很好地匹配以下任何一个:
-
http://www.example.com/test/en/hello_123
-
https://subdomain.example.com/another_test/hello_45
返回给我一个漂亮的,方便的数组,像这样(对于后者):
array(
'protocol' => 'http',
'wildcard' => 'subdomain',
'controller' => 'another_test',
'lang' => 'en',
'name' => "hello_45"
)
我还可以首先包含一个数组,其默认值将被路由器找到的值覆盖。因此,例如,我可以省略<controller>
变量,而只写test
,然后使用数组,添加"controller"=>"test"
。
规则如下:
- 没有匹配,就没有匹配。变量必须存在,如果不存在,则跳过该路由。再见。幸运的是,可选部分不必存在。
-
<>
之间的任何内容都是变量。转义的'<'>
被忽略,即使在。URL中匹配的区域保存到结果数组中,变量名作为关键字。 - 花括号
{}
将部分标记为可选的,并且永远不能在变量<>
中。它们之间的任何内容都可以在目标中忽略—但是,如果为中间的任何变量指定了默认值,则必须将该变量添加到结果数组中,使用名称作为键,并使用默认值作为值。转义大括号将被忽略。 - 变量不必有默认值,但是如果你添加一个,它需要在
=
之后,如<name=default>
。 可以添加 - Regex规则,在名称或默认值之后用空格分隔,并将其括在括号
()
中。转义括号当然会被忽略。 - 最后,你可以把正则表达式规则,在括号里,任何地方,如果你不介意匹配任何东西,没有得到结果。所以,我可以用
(['/]+)
代替<controller>
,但是我必须使用数组来为它设置一个值。
我试过了:
我一直在阅读我能找到的每个路由器的源代码。
到目前为止,我已经完成了几个讨厌的小正则表达式,但是我意识到我完全困惑于如何组合它们并扩展它们。
匹配括号,忽略转义的部分:
{([^{'']*(?:''.[^}'']*)*)}
匹配一个变量,有或没有默认值:
<([^<'']*(?:''.[^>'']*)*)(?:=?([^<>'']*))>
这是一种邪恶的地狱,就像我写了这篇文章:
<([^<'']*(?:''.[^>'']*)*)(?:=?([^<>'']*))(?: ?)('([^{}<>'(')'']+'))?>
(但是,它确实匹配变量和Regex部分。)
有没有人能给我一些提示,甚至是提供类似功能的库的示例源代码?如果这真的是几乎不可能自己编码,有没有一个足够好的库可以使用?
如果您试图匹配域,这个regex101演示应该将这些部分与命名为。
的各个部分匹配。另一方面,如果您试图匹配路由表达式,那么这个regex101演示可以解析到目前为止指定的令牌。
我可能错过了一些规范,但您可以随时留下反馈并解释它的不足之处(甚至可以更新该站点本身的正则表达式并保存新版本)。