在 Laravel 5.3 的中间件中访问路由 URL 参数

Accessing Route URL Parameter in Middleware in Laravel 5.3

Laravel 5.1 更新到 Laravel 5.3 后,我很难访问中间件中的路由 URL 参数。

这是我的路由文件:

Route::group(['middleware' => ['app.access']], function()
{
    Route::resource('apps/{apps}/houses', 'HouseController',
                    ['except' => ['index', 'create', 'edit']]);

    Route::get('apps/{apps}/houses/colour/{colour}', 'HouseController@colourCheck');
    ...
}

Kernel.php RouteMiddleware 更新如下:

protected $routeMiddleware = [
        'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        // Added ones....
        'jwt.auth' => \Tymon\JWTAuth\Middleware\GetUserFromToken::class,
        'jwt.refresh' => \Tymon\JWTAuth\Middleware\RefreshToken::class,
        // Custom Middleware
        'app.access' => \App\Http\Middleware\AppAccess::class,
    ];

Laravel 5.1 中,我能够像这样从中间件访问路由参数,我没有遇到任何问题:

public function handle($request, Closure $next)
{
        $appId = $request->route('apps');
        ...
}

但是,由于升级到 Laravel 5.3,上面的代码开始返回 $appId 作为 null。我还尝试访问 $appId = $request->apps 之类的路由参数,但效果不佳。

然后我更改了中间件以获取 url 参数,如下所示:

public function handle($request, Closure $next)
{
        $appId = $request->route()->parameters('apps');
        ...
}

自从改成上面的之后,中间件好像是为第一个路由工作的。但是,我在转到具有 2 个参数的第二条路线时遇到了问题。由于某种原因,上面的代码失败了,当从中间件返回 $request->route()->parameters('apps') 时,我得到一个这样的数组:

Array
(
    [apps] => 1
    [colour] => green
)

这是为什么?为什么它不只返回 $appId1?我是不是遗漏了什么或者是 Laravel 5.3 中的错误?我希望中间件仅访问 url 中的 appId 参数,而不访问路由中的其他任何参数。有人可以帮我吗?

更新 1:

我尝试更改中间件以获取如下参数:

$parameters = $request->route()->parameters();
$appId = $parameters['apps'];

在上面,我得到了错误:

Undefined index: apps

但是我print_r($parameters);的时候输出是这样的:

Array
(
    [apps] => 1
    [day] => tuesday
)
[]

解法:

最后,我发现这种奇怪行为的原因是 url 中的参数名称。

以下资源路由正在生成路由 url 参数作为 app 而不是 apps。我不知道为什么:

Route::resource('apps/{apps}/houses', 'HouseController',
                        ['except' => ['index', 'create', 'edit']]);

而以下路由正在生成路由 url 参数作为 apps:

Route::get('apps/{apps}/houses/colour/{colour}', 'HouseController@colourCheck');

由于这种奇怪的行为,一些路由返回参数名称 appsnull 和一些显示参数的地方。一旦我在 routes/api.php 和中间件中将所有路由参数重命名为 {app} ,中间件就开始正常工作了。

我不知道为什么资源路由将参数创建为 app,但上面的内容为我修复了错误,至少现在是这样。

在中间件中访问参数有两种方式:

方法一 $request->route('parameter_name'); 这里的parameter_name就是我们在路由中调用的参数

方法二 $request->route()->parameters(); 此方法将 return 一个包含所有参数的数组。

Resource Parameters Are Singular By Default

如果您想保持之前的行为而不是自动单数化资源路由参数,您可以对 AppServiceProvider 中的 singularResourceParameters 方法进行以下调用:

use Illuminate\Support\Facades\Route;

Route::singularResourceParameters(false);

对我来说,这是 Laravel 6 的解决方案。

在路由文件中添加 ->middleware(),如下所示:

Route::resource('orders', 'OrdersController')->middleware('roles:Admin,System');

现在获取中间件中的参数class:

public function handle($request, Closure $next, ...$roles)
{
     // now $roles contains: ['Admin, 'System']
}