通过下面的路由,我希望捕获sitemap.xml
和sitemap-0.xml
。但它只捕获sitemap-0.xml
。你能帮我理解为什么它不起作用吗?
Route::get('/sitemap{suffix?}.xml', 'SitemapController@sitemap');
在控制器中,我这样做:public function sitemap($suffix = null)
当然,我可以制作一条名为Route::get('/sitemap.xml', 'FeedsController@sitemap');
的额外路线,但这似乎是多余的。
如果您通过正则表达式对路由施加约束并使其成为可选的,那么它应该会起作用。请参阅以下路线示例:
<?php
Route::get('/sitemap{suffix?}.xml', 'SitemapController@sitemap')
->where('suffix', '-?([0-9]+)?');
为什么?
Laravel路线以Symfony路线为基础。路线中的可选部分不起作用,因为这是Symfony路线的工作方式。因此,如果可选部件之后有任何内容,Symfony Route将不匹配,因为它将成为必需的。
您已将路线定义为以下
'/sitemap{suffix?}.xml'
请注意,.xml
是在可选部件之后使用的。所以现在需要这个部件{suffix?}
。它必须有一些东西来代替suffix
。这就是为什么sitemap.xml
不起作用,而sitemap-01.xml
起作用的原因。
新手解释
Symfony Route将为sitemap-09.xml
路径生成以下正则表达式:
"{^/sitemap(?P<suffix>[^/.]++).xml$}sDu"
现在取用括号包裹的部分,该部分称为命名捕获组。
(?P<suffix>[^/.]++)
如果您想检查命名捕获组的骨架,则如下所示:
(?P<name>group)
这里,正则表达式的组部分表示匹配任何,除了.xml
之前的正斜杠(/(和点(.(。这意味着它匹配sitemap-0.xml
或将匹配sitemap-0.xml
中代替-0
的任何内容。
因此,当您从sitemap-0.xml
中省略-0
时,组部分(因为它不是可选的(在.xml
之前没有任何匹配项。因此它与CCD_ 20不匹配。
为了解决这个问题,你应该像我上面所做的那样对路由设置一个约束,它会产生以下正则表达式:
"{^/sitemap(?P<suffix>-?(?:[0-9]+)?).xml$}sDu"
在这里,我告诉路由允许-
和[0-9]
可选。因此,它与两者相匹配。