【问题标题】:Middleware on route and in controller路由和控制器中的中间件
【发布时间】:2018-03-09 11:04:41
【问题描述】:

我正在尝试在特定路由以及控制器构造函数内部运行中间件。

但是,在控制器构造函数中定义的中间件似乎没有为包含中间件的路由执行。

这不可能吗? (所有这些中间件都在 kernel.php 中注册,所有中间件在构造函数中都在添加中间件到路由之前工作)

路线

Route::get('/{organization_slug}', function($organization_slug){

    $organization = \App\Organization::where('slug', '=', $organization_slug)->first();

    $app = app();
    $controller = $app->make('\App\Http\Controllers\OrganizationController');
    return $controller->callAction('details', $parameters = array($organization->id));

})->middleware('verifyorganizationslug');

控制器构造函数

    public function __construct()
    {
        $this->middleware('auth', ['only' => ['create', 'update', 'store']]);
        $this->middleware('accountactive', ['only' => ['create', 'update', 'store']]);
        $this->middleware('ownsorganization', ['only' => ['update']]);
        $this->middleware('verifyorganization', ['only' => ['details']]);

    }

【问题讨论】:

    标签: php laravel laravel-5


    【解决方案1】:

    gatherMiddleware中,路由中间件与控制器中间件合并后选择唯一的中间件。

    public function gatherMiddleware()
    {
        if (! is_null($this->computedMiddleware)) {
            return $this->computedMiddleware;
        }
        $this->computedMiddleware = [];
        return $this->computedMiddleware = array_unique(array_merge(
            $this->middleware(), $this->controllerMiddleware()
        ), SORT_REGULAR);
    }
    

    如果您正在查看映射到 details 方法的操作,您应该看到 verifyorganizationslug 然后 verifyorganization 已应用。

    根据您查看的路由,computedMiddleware 将始终应用verifyorganizationslug 中间件,并在控制器中为该路由指定其他中间件。

    Route controller getMiddleware filters all middleware not belonging in that method.

    public function getMiddleware($controller, $method)
    {
        if (! method_exists($controller, 'getMiddleware')) {
            return [];
        }
        return collect($controller->getMiddleware())->reject(function ($data) use ($method) {
            return static::methodExcludedByOptions($method, $data['options']);
        })->pluck('middleware')->all();
    }
    

    重要

    现在,您的代码围绕请求-响应 Pipeline 运行,这可确保按上述顺序应用中间件。你失去了控制器中间件的应用程序isControllerAction returns false,因为它是Closure而不是string

    快进,你要使用:

    Route::get('/{organization_slug}', '\App\Http\Controllers\FooController@details')
         ->middleware('foo');
    

    然后在控制器内部解析organization_slug

    public function details(Request $request, $organisation_slug)
    {
       $organization = \App\Organization::where('slug', '=', $organization_slug)
                           ->first();
       ...
    }
    

    或者考虑使用Route bindingorganization_slug路由参数绑定到组织的一个实例。✌️

    【讨论】:

    • 我的控制器构造函数的最后一行将中间件verifyorganization(与路由文件中应用的中间件verifyorganizationslug不同)应用于details函数。当显示在我的路由中调用详细信息方法时,这不会执行。
    猜你喜欢
    • 2017-01-13
    • 2017-12-18
    • 2017-02-27
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 2014-08-20
    • 1970-01-01
    • 2019-12-21
    相关资源
    最近更新 更多