在 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 后,上述代码开始返回 $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
)
这是为什么呢?为什么它不只返回$appId
即1
?我错过了什么还是 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')
,但它返回为null
。 apps
是routes/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?