正则表达式匹配网址

时间:2013-04-13 00:17:45

标签: php regex routing

在PHP中,klein路由将匹配尽可能多的路由。 我设置的2条路线是冲突的。他们是:

$route1: '/websites/[i:websiteId]/users/[i:id]?'

$route2: '/websites/[i:websiteId]/users/[a:filename].[json|csv:extension]?'

这是我想要匹配的网址,我认为应该匹配第一个而不是第二个,是:

/api/v1-test/websites/100/users/4

为这两者制作的正则表达式是:

$regex1: `^/api(?:/(v1|v1-test))/websites(?:/(?P<websiteId>[0-9]++))/users(?:/(?P<id>[0-9]++))?$`

$regex2: `^/api(?:/(v1|v1-test))/websites(?:/(?P<websiteId>[0-9]++))/users(?:/(?P<filename>[0-9A-Za-z]++))(?:\.(?P<extension>json|csv))?$`

我的意思是如果没有'.csv'或'.json'就不匹配。问题是它匹配两条路线。对于第二个,结果文件名为'4',扩展名为空。

发送/api/v1-test/websites/100/users/users.csv正常工作,只匹配第二条路线。

我只能控制路线,而不是正则表达式或匹配。 感谢。

2 个答案:

答案 0 :(得分:0)

这一点

(?:\.(?P<extension>json|csv))?

在你的第二个正则表达式的末尾导致它匹配是否由于最后的?而存在文件名。问号意味着0 or 1 of the previous expression。摆脱它,至少,字符串只有当它们具有扩展名时才匹配这个正则表达式。

要进行此更改,只需从第二条路线中移除问号,如下所示:

$route2: '/websites/[i:websiteId]/users/[a:filename].[json|csv:extension]'

答案 1 :(得分:0)

问题在于match_type的定义真的很奇怪:

$match_types = array(
            'i' => '[0-9]++',
            'a' => '[0-9A-Za-z]++',
[...]

因此,您无法真正捕获与[a-zA-Z]对应的序列...我看到的唯一选择是使用3条路线:

$route1: '/websites/[i:websiteId]/users/[i:id]?'
$route2: '/websites/[i:websiteId]/users/[a:filename]'
$route3: '/websites/[i:websiteId]/users/[a:filename].[json|csv:extension]'

并为路线2和3分配相同的动作。然后你会有:

  • /api/v1-test/websites/100/users/与1
  • 匹配
  • /api/v1-test/websites/100/users/4与1
  • 匹配
  • /api/v1-test/websites/100/users/test与2
  • 匹配
  • /api/v1-test/websites/100/users/test.csv与3
  • 相匹配

这似乎就是你想要的行为。

Abother(更容易)的解决方案是利用文档中的这一点:

Routes automatically match the entire request URI.
If you need to match only a part of the request URI
or use a custom regular expression, use the @ operator.

然后您可以像这样定义您的路线:

$route1: '@/websites/[0-9]+/users/[0-9]*$'
$route1: '@/websites/[0-9]+/users/[a-zA-Z]+(\.[a-zA-Z]+)?$'