使用正则表达式匹配复杂路线

时间:2015-09-25 16:02:54

标签: php regex model-view-controller url-routing matching

我正在为我正在处理的基于PHP的大型网站开发一个请求路由器,但是我在试图为我的路由使用自定义表达式时遇到困难。

虽然我知道有预先制作的替代品和路由器可以让我的生活更轻松,并且具有相同的功能(事实上,我一直在寻找他们的源代码来尝试解决这个问题),我是仍然是一个编程学生,学习如何创建我自己只能是一件好事!

示例:

以下是我的一个路线表达式的示例:

  • <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>替换([\/]+),但之后我必须使用数组为它设置一个值。

我尝试过的事情:

我一直在阅读我能找到的每个路由器的源代码。

到目前为止,我已经做了几个讨厌的小正则表达式,但我意识到我完全混淆了如何将它们聚合并扩展它们。

  • 这与括号相符,忽略转义的括号:{([^{\\]*(?:\\.[^}\\]*)*)}

  • 这匹配一个变量,有或没有默认值:<([^<\\]*(?:\\.[^>\\]*)*)(?:=?([^<>\\]*))>

  • 这是一种不圣洁的地狱,其中的一些让我写这篇文章:<([^<\\]*(?:\\.[^>\\]*)*)(?:=?([^<>\\]*))(?: ?)(\([^{}<>\(\)\\]+\))?> (但它确实匹配变量和正则表达式部分。)

有人可以从提供类似功能的库中提供任何提示,甚至示例源代码吗?如果这对我自己编码几乎是不可能的,那么有一个足够好的库吗?

1 个答案:

答案 0 :(得分:1)

如果您要尝试匹配域,this regex101 demo应该将这些部分与名为的各个部分匹配。

另一方面,如果您尝试匹配路由表达式,this other regex101 demo能够解析您目前指定的令牌。

我可能错过了一些规范,但您可以随时留下反馈并解释它的不足之处(甚至更新该网站上的正则表达式并保存更新的版本)。