[英]Optional parameter in the middle of a route
Is there any way to add an optional parameter in the middle of a route ?有没有办法在路由中间添加一个可选参数?
Example routes:示例路线:
/things/entities/
/things/1/entities/
I tried this, but it does not work:我试过这个,但它不起作用:
get('things/{id?}/entities', 'MyController@doSomething');
I know I can do this...我知道我可以做到这一点...
get('things/entities', 'MyController@doSomething');
get('things/{id}/entities', 'MyController@doSomething');
... but my question is: Can I add an optional parameter in the middle of a route? ...但我的问题是:我可以在路由中间添加一个可选参数吗?
No. Optional parameters need to go to the end of the route, otherwise Router wouldn't know how to match URLs to routes.不可以。可选参数需要放在路由的末尾,否则 Router 不知道如何将 URL 与路由匹配。 What you implemented already is the correct way of doing that:
您已经实施的是正确的做法:
get('things/entities', 'MyController@doSomething');
get('things/{id}/entities', 'MyController@doSomething');
You could try doing it with one route:你可以尝试用一条路线来做:
get('things/{id}/entities', 'MyController@doSomething');
and pass * or 0 if you want to fetch entities for all things, but I'd call it a hack.并传递* 或 0如果你想为所有东西获取实体,但我称之为黑客。
There are some other hacks that could allow you to use one route for that, but it will increase the complexity of your code and it's really not worth it.还有一些其他的 hack 可以让您为此使用一种路线,但这会增加您的代码的复杂性,这真的不值得。
The "correct" answer for this question is;这个问题的“正确”答案是; No, you can't and shouldn't use an optional parameter unless it's at the end of the route/url.
不,您不能也不应该使用可选参数,除非它位于路由/url 的末尾。
But, if you absolutely need to have an optional parameter in the middle of a route, there is a way to achieve that.但是,如果您绝对需要在路由中间有一个可选参数,那么有一种方法可以实现这一点。 It's not a solution I would recommend, but here you go:
这不是我推荐的解决方案,但您可以这样做:
routes/web.php
: 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
: 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
: 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>
Both links will trigger the first
-method in TestController
.两个链接都将触发
TestController
的first
方法。 The second
-method will never be triggered. second
方法永远不会被触发。
This solution works in Laravel 6.3, not sure about other versions.此解决方案适用于 Laravel 6.3,不确定其他版本。 And once again, this solution is not good practice.
再一次,这个解决方案不是好的做法。
Having the optional parameter in the middle of the route definition like that, will only work when the parameter is present.像这样在路由定义的中间有可选参数,只有当参数存在时才会起作用。 Consider the following:
考虑以下:
things/1/entities
, the id
parameter will correctly get the value of 1
.things/1/entities
, id
参数将正确获得1
的值。things/entities
, because Laravel uses regular expressions that match from left to right, the entities
part of the path will be considered to be the value of the id
parameter (so in this case $id = 'entitites';
).things/entities
,因为 Laravel 使用从左到右匹配的正则表达式,路径的entities
部分将被认为是id
参数的值(所以在这种情况下$id = 'entitites';
) . This means that the router will not actually be able to match the full route, because the id
was matched and it now expects to have a trailing /entities
string as well (so the route that would match would need to be things/entities/entities
, which is of course not what we're after).id
已匹配,现在它也希望有一个尾随/entities
字符串(因此匹配的路由需要是things/entities/entities
,这当然不是我们所追求的)。 So you'll have to go with the separate route definition approach.因此,您必须采用单独的路由定义方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.