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

Posted

技术标签:

【中文标题】在 Laravel 5.3 的中间件中访问路由 URL 参数【英文标题】:Accessing Route URL Parameter in Middleware in Laravel 5.3 【发布时间】:2017-03-06 14:27:09 【问题描述】:

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 后,上述代码开始返回 $appIdnull。我还尝试访问像$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');

由于这种奇怪的行为,一些路由返回 null 的参数名称 apps 和一些显示参数的位置。一旦我在routes/api.php 和中间件中将所有路由参数重命名为app,中间件就开始按应有的方式工作。

我不知道为什么资源路由将参数创建为app,但以上为我修复了错误,至少目前是这样。

【问题讨论】:

route() 方法应该在中间件 Laravel 5.3 中工作以获取路由参数。对我来说很好。 @schellingerht 对我来说,route() 方法在 Laravel 5.3 中总是返回 null。我已经在Kernel.php 中将中间件添加到RouteMiddleware 并且它仍然为空。我知道 Laravel 5.3 已将路由文件更改为 api 和 web 并且我使用的中间件是用于 api 组的,这有什么改变吗?我不明白为什么中间件中的route() 在更新后显示为空。 【参考方案1】:

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

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

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

【讨论】:

当我尝试方法 1 时,我得到它为空。在方法2中,我只想获取appId,所以当我将其添加为$request->route()->parameters('apps')时,当url具有多个参数时,我仍然会获取所有参数的数组,就像我的OP中的示例一样。 对于方法 1 - 确保在 route.php 中为 parameter_name 使用相同的名称。至于Route::get('apps/apps/houses/colour/colour', 'HouseController@colourCheck');,你可以称它为$request->route('apps')$request->route('colour')。而$request->route()->parameters(); 不接受任何参数,它总是返回一个数组。 感谢您的回复@AmitGupta 我确实使用route() 方法作为$request->route('apps'),但它返回为nullappsroutes/api.php 中调用的参数名称。我还在Kernel.php 中将中间件添加到RouteMiddleware,但它仍然返回为null。 我尝试了第二种方法从数组中获取appId 参数,但这也不起作用。我已经用我尝试过的内容以及使用print_r 时得到的输出更新了我的帖子。 用目前有效的解决方案更新了我的帖子。谢谢你的回答。【参考方案2】:

Resource Parameters Are Singular By Default

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

use Illuminate\Support\Facades\Route;

Route::singularResourceParameters(false);

【讨论】:

啊...感谢@HarryBosh 提供的链接。现在可以理解为什么路由参数仅在 5.3 中被单数化了。【参考方案3】:

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

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

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

现在检索中间件类中的参数:

public function handle($request, Closure $next, ...$roles)

     // now $roles contains: ['Admin, 'System']

【讨论】:

以上是关于在 Laravel 5.3 的中间件中访问路由 URL 参数的主要内容,如果未能解决你的问题,请参考以下文章

任何想法如何使用 vue js 和 vue 路由器在 laravel 5.3 中进行基于会话的身份验证

Laravel 5.3:如何在全局中间件中使用 Check Auth?

Laravel 5.3 + Passport:总是未经身份验证的错误

Laravel 5.3 个人访问令牌 500

laravel 路由重定向问题(laravel 5.3)

Lumen 5.3 未定义变量:闭包