【问题标题】:Laravel controllers with roles带有角色的 Laravel 控制器
【发布时间】:2017-10-21 01:42:07
【问题描述】:

我有一个应用程序,它将是一个 SaaS 并且正在利用用户角色。当然,控制器需要根据用户角色或权限转发不同的数据,但是我认为这种方法可能会导致我使用庞大的控制器,我想知道是否有更聪明的方法来做到这一点?例如我的用户创建方法:

public function create()
{
    if (Auth::user()->isAdmin()) {
        $clinics = Clinic::pluck('name', 'id');
        $roles = Role::pluck('display_name', 'id');
    }
    else{
        $clinics = Clinic::where('id', Auth::user()->clinic_id)->get()->pluck('name', 'id');
        $roles = Role::where('name', '!=', 'admin')->get()->pluck('display_name', 'id');
    }

    $states = State::pluck('name', 'id');
    $cities = City::pluck('name', 'id');

    return view('users.create', compact('user', 'clinics', 'states', 'cities', 'roles'));
}

当我只实现管理员和非管理员用户时,现在这还可以,但是当角色变得复杂时,有没有更简洁的方法来组装它?

【问题讨论】:

  • 您可以使用模型存储库并将用户角色检查移入其中。

标签: php laravel roles


【解决方案1】:

我建议你看看 Laravel 文档的Scopes。您可以将范围附加到您的模型以获得相同的结果。

此解决方案不会帮助您删除代码复杂性(即在模型中移动),但会帮助您消除代码重复,因为您将在应用程序开发过程中多次遇到相同的“如果”...

您的诊所的本地范围可能是这样的

class Clinic extens Model {
    [...]
    public function scopeCanSee($query)
    {
        $user = Auth::user();
        if(!$user->isAdmin())
            return $query->where('id', $user->clinic_id);
        return $query;
    }
}

然后在您的控制器中,您可以通过这种方式过滤结果

public function create()
{
    $clinics = Clinic::canSee()->pluck('name', 'id');
    [...]

    $states = State::pluck('name', 'id');
    $cities = City::pluck('name', 'id');

    return view('users.create', compact('user', 'clinics', 'states', 'cities', 'roles'));
}

全局作用域

另一种方法是使用全局作用域(但我还没有测试过)

class Role extends Model
{
    protected static function boot()
    {
        parent::boot();
        static::addGlobalScope(new RolesScope);
    }
}
class Clinic extends Model
{
    protected static function boot()
    {
        parent::boot();
        static::addGlobalScope(new ClinicsScope);
    }
}

和范围类似

class ClinicsScope implements Scope
{
    public function apply(Builder $builder, Model $model)
    {
        $user = Auth::user();
        $builder->where('id', $user->clinic_id);
    }
}

【讨论】:

  • 如果我只想按 ID 过滤,我仍然需要在我的模型中复制代码,对吧?
  • 你能准确解释一下你的意思吗?
  • @Norgul 您可以将参数传递给范围,因此您可以为不同的 id 重用单个范围。
  • 例如,您的scopeCanSee() 函数现在适用于Clinic。如果我要在OtherModel 上执行相同类型的过滤(以便只有管理员可以看到完整列表),我会在OtherModel 上复制相同的功能。有没有办法避免重复?
  • 如果您要过滤的属性始终相同,则可以应用相同的全局范围(在我之前的示例中,由于您的问题而有所不同)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-30
  • 2016-04-07
  • 2013-04-27
  • 1970-01-01
  • 2017-10-05
  • 1970-01-01
相关资源
最近更新 更多