基于当前经过身份验证的用户的模型过滤器

Model filters based on the currently authenticated user

我正在开发一个应用程序,其中每个用户都被分配到一个特定的区域。例如,用户 1 属于区域 'Phoenix',用户 2 属于 'Scottsdale',用户 3 属于 'Tempe'。每个用户的区域在 region_id 列中定义。

该应用针对 3 种不同的用户模型(它是一个包含区域经理、供应商和客户的市场)有 3 个独立的守卫。实际上,应用程序中的每个模型都有一个 region_id 列,用于标识资源属于哪个区域。

我想简化资源的查询方式。目前,我直接在控制器中过滤每个 model/resource,例如:

$customers = Customer::where('region_id', Auth::user()->region_id);

我想在全局级别设置此类过滤器,以确保每个经过身份验证的用户只能看到来自他们自己区域的记录。这对于显示当前区域中的记录列表特别重要,而不是检查用户是否可以 access/edit 特定的单个记录。

我已经调查了 Query Scopes,但我无法通过它们访问当前经过身份验证的用户。我可以访问当前用户的唯一情况是在闭包中定义了全局范围,但这违背了不必在每个模型中定义相同逻辑的目的(即我无法将过滤逻辑提取到查询范围class).

什么是值得考虑的替代方法?如何根据当前已验证用户的 属性 设置全局模型过滤器?

制作一个 RegionalModel 并使用 region_id 字段扩展所有 Models 怎么样?然后,在您的 RegionalModel 中创建一个类似 forUser(User $user) 的范围来应用您的过滤器。

class RegionalModel extends Model {

    public function scopeForUser($query, User $user) {
        // Apply filter here
    }

}

那么您的 Customer 模型可能如下所示

class Customer extends RegionalModel {

    // Code here

}

然后当你想获得客户列表时

$user = Auth::user();
$customers = Customer::forUser($user)->get();

我在 GitHub 上的 Laravel 框架问题跟踪器上发布了一个类似的问题作为可能的错误(不确定这种行为是否是预期的)并在那里找到了答案。

事实证明,您无法在全局查询作用域构造函数中访问经过身份验证的用户,但可以在 apply() 方法中访问它。

所以代替:

public function __construct() {
    $this->region_id = Auth::user()->region_id;
}

public function apply(Builder $builder, Model $model)
{
    $builder->where('region_id', $this->region_id);
}

我必须做的:

public function apply(Builder $builder, Model $model)
{
    $region_id = Auth::user()->region_id;

    $builder->where('region_id', $region_id);
}

Link 到 GitHub here.

上的问题