如何传递参数到控制器中间件


Laravel how to pass parameters to controller middleware

我想做一些事情,但我甚至不知道怎么做。

将参数传递给中间件,我这样做:

Route::put('post/{id}', ['middleware' => 'role:editor', function ($id) {
    //
}]);  

来自laravel文档。然后在句柄函数中获取参数…

但是laravel建议在控制器的__construct中声明中间件的使用,而不是在路由中。

所以…

public function __construct() {
       $this->middleware('auth');
}

但是我不知道如何传递参数给控制器。

您可以在中间件中访问url参数,如下所示:

routes.php

Route::get('/test/{id}', ['uses' => 'Test@test']);
测试控制器

<?php
namespace App'Http'Controllers;
class Test extends Controller
{
    /**
     * Test constructor.
     */
    public function __construct()
    {
        $this->middleware('test');
    }
    public function test()
    {
        return 'sample';
    }
测试中间件

<?php namespace App'Http'Middleware;
use Closure;
class Test
{
    public function handle($request, Closure $next)
    {
        dd($request->id);
        return $next($request);
    }
}

**不要忘记更新Kernel.php来激活中间件

    protected $routeMiddleware = [
        'auth' => 'App'Http'Middleware'Authenticate::class,
        'auth.basic' => 'Illuminate'Auth'Middleware'AuthenticateWithBasicAuth::class,
        'guest' => 'App'Http'Middleware'RedirectIfAuthenticated::class,
        'test' => 'App'Http'Middleware'Test::class,
    ];

不要将中间件放在控制器中。尽量将业务逻辑置于控制器之外。

让你的中间件文件。

php artisan make:middleware MyMiddlewareDoesThings

现在在您的文件中,找到$handle函数。

public function handle($request, Closure $next)

在请求和闭包之后添加参数

public function handle($request, Closure $next, $role)

现在$role将包含role:value的值,从您的示例中将是$editor

@ muhammadad -sumon-molla-selim的答案实际上是问题中最好的答案,但它泄露了解释

凭借我的知识,我能够遵循他的指导方针,所以这里是一个完整的例子加上一个用例,其中路由的中间件或请求参数是不可能的。

我有一个抽象的CRUDControllerBase,它被许多子控制器扩展。每个子控制器需要一个不同的权限来执行模型上的任何操作,除了index/show。

因此,我被迫动态地将权限(字符串)从控制器传递到中间件,这是基本结构:
// App'Http'Controllers'CRUDControllerBase.php
abstract class CRUDControllerBase extends Controller
{
    /**
     * @var string The needed permission to call store or update
     * If null, permission is granted to every users
     */
    protected ?string $permission = null;
    public function __construct()
    {
        // Here I need to pass to VerifyUserPermission the controller's permission
        $this->middleware(VerifyUserPermission::class)
             ->except(['index', 'show']);
    }
}
// App'Http'Controllers'DocumentController.php
class DocumentController extends CRUDControllerBase
{
    protected ?string $permission = 'documents';
}
// App'Http'Controllers'EventController.php
class EventController extends CRUDControllerBase
{
    protected ?string $permission = 'events';
}

我在@muhammad-sumon-molla-selim的回答下解决了这个问题:

// App'Http'Middleware'VerifyUserPermission.php
// Create the VerifyUserPermission middleware, which accepts the permission string
class VerifyUserPermission
{
    public function handle(Request $request, Closure $next, ?string $permission): mixed
    {
        $user = $request->user();
        // If a permission is needed but the user doesn't have it, abort
        if ($permission && !$user->$permissionField) {
            abort(401);
        }
        return $next($request);
    }
}
// App'Http'Kernel.php
// Register the middleware
class Kernel extends HttpKernel
{
    protected $routeMiddleware = [
        'auth' => 'App'Http'Middleware'Authenticate::class,
        'auth.basic' => 'Illuminate'Auth'Middleware'AuthenticateWithBasicAuth::class,
        // [...]
        'permission' => 'App'Http'Middleware'VerifyUserPermission::class
    ];
}
// App'Http'Controllers'CRUDControllerBase.php
// Then just register the middleware into the CRUDControllerBase's constructor
abstract class CRUDControllerBase extends Controller
{
    protected ?string $permission = null;
    public function __construct()
    {
        // 'documents' permission will be needed for Documents' edition
        // 'events' permission will be needed for Events' edition
        // And so on for many others controllers
        $this->middleware("permission:$this->permission")
             ->except(['index', 'show']);
    }
}

我已经解决了这个问题,用这个:

Route::get('post/{id}', function () {
    // Your controller method here
})->middleware('myMiddleware');

在中间件中:

namespace App'Http'Middleware;
use Closure;
class MyMiddleware
{
    public function handle($request, Closure $next)
    {
        $id = $request->route('id');
        // Your middleware logic here
        return $next($request);
    }
}

如果你想在控制器的__construct中获取参数,你可以这样做:

class HomeController extends 'BaseController
{
    public function __construct()
    {
        $this->routeParamters = Route::current()->parameters();
    }
}