路径中间的可选参数

时间:2015-07-23 10:10:31

标签: php laravel laravel-5

有没有办法在路线中间添加可选参数?

示例路线:

/things/entities/
/things/1/entities/

我试过这个,但它不起作用:

get('things/{id?}/entities', 'MyController@doSomething');

我知道我可以这样做......

get('things/entities', 'MyController@doSomething');
get('things/{id}/entities', 'MyController@doSomething');

...但我的问题是:我可以在路线中间添加一个可选参数吗?

3 个答案:

答案 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,这当然不是我们追求的目标。

所以你必须采用单独的路线定义方法。