【问题标题】:Inject Route Action on Controller在控制器上注入路由操作
【发布时间】:2018-05-13 14:56:36
【问题描述】:

我已经制作了一个角色中间件来检查用户是否具有特定的角色:

namespace App\Http\Middleware;

use Closure;

class CheckRole
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if ($request->user() === null) {
            return response("Insufficient permissions", 401);
        }
        $actions = $request->route()->getAction();
        $roles = isset($actions['roles']) ? $actions['roles'] : null;
        if ($request->user()->hasAnyRole($roles) || !$roles) {
            return $next($request);
        }
        return response("Insufficient permissions", 401);
    }
}

如果我想检查特定角色中的某个角色,这很容易。我只需要添加中间件和一个名为roles 的附加操作。例如:

Route::get('payments/{id}/pay', [
    'uses' => 'PaymentController@aprove',
    'as' => 'payments.aprove',
    'middleware' => 'roles',
    'roles' => [User::ADMINISTRATOR, User::SPOT_MANAGER, User::SELECTION_PROCESS_MANAGER],
]);

这样做可以按预期工作。但是,我有一些路线是 Route::resource 而不是 getpost 或类似的东西。 Laravel 不允许在资源中指定 roles => [...]

文档说,如果我想在资源上注入中间件,我 should do this on controller。但是我不能像以前在任何地方的正常路线中那样指定roles => [...]!我怎么能这样做?

提前致谢。

【问题讨论】:

    标签: php laravel controller routing laravel-5.5


    【解决方案1】:

    由于您在定义资源路由时无法控制要使用的 'action' 数组,并且中间件参数不合适,您可以定义自己的 ResourceRegistrar 并将其绑定到容器,以便路由器将在 @ 上使用它987654322@ 来电。

    您将扩展Illuminate\Routing\ResourceRegistrar 并覆盖getResourceAction 方法以检查$options 数组以查看是否...假设定义了一个名为action 的键。如果是这样,则将此数组合并到 $action 数组中,现在通过 Route::resource 定义的所有路由都可以接受 action 的选项键,该键采用您的额外操作值。

    允许这样的定义:

    Route::resource('blah', 'BlahController', [
        'action' => ['roles' => ['admin', 'editor']]
    ]); 
    

    这样的事情“应该”做:

    protected function getResourceAction($resource, $controller, $method, $options)
    {
        $action = parent::getResourceAction($resource, $controller, $method, $options);
    
        if (isset($options['action'])) {
            $action += $options['action'];
        }
    
        return $action;
    }
    

    register 的服务提供者中绑定:

    $this->app->bind(
        \Illuminate\Routing\ResourceRegistrar::class,
        \App\Your\ResourceRegistrar::class
    );
    

    您可以更进一步,使其特定于角色,这样您就可以这样做:

    Route::resource('blah', 'BlahController', ['roles' => ['admin', 'editor']]);
    

    【讨论】:

      【解决方案2】:

      您可以通过使用中间件参数来避免这种情况,因此您可以将参数传递给您的中间件。这种“动作”方法对于某些事情来说是一个很好的解决方法,但中间件需要参数,所以除非你在更多地方需要这些参数,否则真的不需要。

      'middleware' => 'roles:admin,editor,...'
      

      从字面上看,文档中的中间件参数示例是用户角色检查。

      Laravel 5.5 Docs - Middleware - Parameters

      也没有“注入”。你只是告诉路由器你想要中间件,没有任何东西注入其他任何东西。

      【讨论】:

      • 我在文档中读到过这个,但是这样传递参数很丑。
      • 除非您想创建自己的 ResourceRegistrar,否则您不会在资源路由方面走得太远。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-08
      • 2015-03-10
      • 1970-01-01
      • 2023-03-07
      • 2012-08-14
      • 2011-12-03
      相关资源
      最近更新 更多