在Laravel中,我试图实现在URL中具有可变数量类别的能力,其次是slug.例如:
www.trashaccount.com/category1/category2/slug
我在Laravel中使用路线模式来识别类别
Route::pattern('cat', '([-a-zA-Z0-9]+\/?)*');
演示/测试路线如下所示:
Route::get('test/{cat}/{slug}', function($cat, $slug) {
$categories = explode('/', $cat);
$i = 1;
foreach($categories as $category) {
echo "category " . $i . ": " . $category . "<br>";
$i++;
}
echo "slug: " . $slug . "<br>";
});
可以在www.trashaccount.com/test/{cat}/…/{slug}进行测试
该代码成功地提取了任意数量的长度可变的类别.例如,这有效:
http://www.trashaccount.com/test/cat1/cat2/cat3/abcdefghijklmnopqrstuvwxyzabcdevg/my-slug
中断之处在于最后一个元素{slug}的字符数.由于某些原因,任何超出17个字符的字符都会引发NotFoundHttpException.因此,这不起作用:
http://www.trashaccount.com/test/cat1/abcdefghijklmnopqr
但是,如果您只是删除“ r”(18h字符),它将起作用.
为了澄清(由于我的帖子在另一个论坛上被误解了),您可以键入任意多个类别,它们可以是任意长度(遵守HTTP限制),它们将被接受并处理.我标记为{slug}的最后一个元素不能超过17个字符,而不会引发NotFoundHttpException错误.
有人知道我在做什么错吗?
谢谢!
解决方法:
老实说,我觉得这种行为很奇怪.
我什么也没做,所以我开始研究Laravel的内部代码,看看有什么问题,我得出的结论是,如果路由的最后一部分长于17个字符,那么它将失败.
一切发生在Illuminate\Routing\Matching\UriValidator->matches() line 25年.
这是一些使用/ test / first-category / testingslug的调试打印:
preg_match("#^/assets/(?P(?!\.\.)(.*))$#s", "/test/first-category/testingslug");
// successful
preg_match("#^/test/(?P([-a-zA-Z0-9]+\/?)*)/(?P[^/]++)$#s", "/test/first-category/testingslug");
category 1: first-category
slug: testingslug
一切正常,直到我尝试使用超过17个字符的子弹为止.
我尝试使用/ test / first-category / testingslugmuchlonger:
preg_match("#^/assets/(?P(?!\.\.)(.*))$#s", "/test/first-category/testingslugmuchlonger");
// fails
preg_match("#^/test/(?P([-a-zA-Z0-9]+\/?)*)/(?P[^/]++)$#s", "/test/first-category/testingslugmuchlonger");
preg_match("#^/assets/(?P(?!\.\.)(.*))$#s", "/test/first-category/testingslugmuchlonger");
// fails again
preg_match("#^/test/(?P([-a-zA-Z0-9]+\/?)*)/(?P[^/]++)$#s", "/test/first-category/testingslugmuchlonger");
之所以重复,是因为框架会检查Illuminate/Routing/RouteCollection.php->match() line 141中是否存在具有相同路由但方法不同的替代路由.
现在,我尝试在单独的文件中调试这两个preg_matc():
$works = null;
preg_match("#^/test/(([-a-zA-Z0-9]+\/?)*)/([^/]++)$#s", "/test/first-category/testingslug", $works);
var_dump($works);
$fails = null;
preg_match("#^/test/(([-a-zA-Z0-9]+\/?)*)/([^/]++)$#s", "/test/first-category/testingslugmuchlonger", $fails);
var_dump($fails);
这就是他们的回报:
array(4) {
[0]=>
string(32) "/test/first-category/testingslug"
[1]=>
string(14) "first-category"
[2]=>
string(14) "first-category"
[3]=>
string(11) "testingslug"
}
array(0) {
}
我认为preg_match一定有问题(?).