有没有办法在路线中间添加可选参数?
示例路线:
/things/entities/
/things/1/entities/
我试过这个,但它不起作用:
get('things/{id?}/entities', 'MyController@doSomething');
我知道我可以这样做......
get('things/entities', 'MyController@doSomething');
get('things/{id}/entities', 'MyController@doSomething');
...但我的问题是:我可以在路线中间添加一个可选参数吗?
答案 0 :(得分:4)
没有。可选参数需要到达路由的末尾,否则路由器不知道如何将URL与路由匹配。你已经实现的是正确的方法:
get('things/entities', 'MyController@doSomething');
get('things/{id}/entities', 'MyController@doSomething');
您可以尝试使用一条路线:
get('things/{id}/entities', 'MyController@doSomething');
并传递 *或0 ,如果您想获取所有内容的实体,但我称之为黑客。
还有一些其他黑客可以让你使用一条路线,但它会增加你的代码的复杂性,而且它真的不值得。
答案 1 :(得分:3)
此问题的“正确”答案是;不,除非在路由/网址的末尾,否则您不能也不应使用可选参数。
但是,如果您绝对需要在路线中间添加可选参数,则可以通过一种方法来实现。这不是我建议的解决方案,但您可以使用:
routes/web.php
:
// Notice the missing slash
Route::get('/test/{id?}entities', 'Pages\TestController@first')
->where('id', '([0-9/]+)?')
->name('first');
Route::get('/test/entities', 'Pages\TestController@second')
->name('second');
app/Http/Controllers/Pages/TestController.php
:
<?php
namespace App\Http\Controllers\Pages;
use App\Http\Controllers\Controller;
class TestController extends Controller
{
public function first($id = null)
{
// If $id is not null, it will have a trailing slash
$id = rtrim($id, '/');
return 'First route with: ' . $id;
}
public function second()
{
return 'Second route';
}
}
resources/views/test.blade.php
:
<!-- Notice the trailing slash on id -->
<!-- Will output http://myapp.test/test/123/entities -->
<a href="{{ route('first', ['id' => '123/']) }}">
First route
</a>
<!-- Will output http://myapp.test/test/entities -->
<a href="{{ route('second') }}">
Second route
</a>
两个链接都将触发first
中的TestController
方法。 second
方法将永远不会被触发。
此解决方案在Laravel 6.3中有效,不确定其他版本。再一次,这种解决方案不是一个好习惯。
答案 2 :(得分:2)
将可选参数放在路径定义的中间,只有当参数存在时才会起作用。请考虑以下事项:
things/1/entities
时,id
参数将正确获取1
的值。things/entities
时,由于Laravel使用从左到右匹配的正则表达式,路径的entities
部分将被视为id
参数的值(所以在这种情况下$id = 'entitites';
)。这意味着路由器实际上无法匹配完整路由,因为id
已匹配,现在它也希望有一个尾随/entities
字符串(因此需要匹配的路由)成为things/entities/entities
,这当然不是我们追求的目标。所以你必须采用单独的路线定义方法。