【问题标题】:Laravel custom collection or custom query builder?Laravel 自定义集合还是自定义查询构建器?
【发布时间】:2021-07-10 14:25:55
【问题描述】:

我有那个项目的订单有状态,每个状态都可以看到,这取决于用户是否有权管理它。我尝试使用自定义集合,但缺点是默认情况下它不可分页, 这是代码

class OrdersCollection extends Collection
{
    public function allowedForUser(User $user)
    {
        return $this->filter(function ($order) use ($user) {
            return $user->can(sprintf('manage %s orders', strtolower($order->status)));
        });
    }
}

这是我尝试使用它的方式

$orders = Order::withoutTrashed()
            ->allowedForUser(Auth::user())
            ->paginate(50);

编辑:

为了避免过滤表中的 20k+ 行,我想出了这个自定义构建器

class OrderBuilder extends Builder
{
    public function WhereAllowedForUser(User $user)
    {
        $permissions = $user->permissions()
            ->where('name', 'like', 'manage % orders')
            ->pluck('name')
            ->map(function ($item) {
                return str_replace('manage ', '', str_replace(' orders', '', $item));
            });

        return $this->whereIn('status', $permissions);
    }
}

【问题讨论】:

  • 那么,问题出在哪里?它不是可分页的?
  • 是的,它不能分页,如果我使用上面的代码进行分页,我会得到Call to undefined method Illuminate\Database\Eloquent\Builder::allowedForUser()
  • 是的,那是因为你还在Builder,不是收藏。我认为一个好的方法是创建一个范围查询并传递您需要的数据,然后根据您的需要过滤(在数据库上)。
  • 我可以使用任何代码示例吗?我试图提取权限名称,然后使用 whereIn,但是例如名为“管理拒绝订单”的权限,订单状态被拒绝。我找不到干净的方法。
  • Order 是一个模型,既然可以将 allowedForUser 放在模型类中,为什么还要扩展一个集合呢?然后过滤get()值

标签: php laravel


【解决方案1】:

你必须为你的模型使用scoped queries

这个想法是让你将一个值传递给范围并用它做你想要/需要的:

class Order extends Model
{
    public function scopeWhereAllowedForUser($query, User $user)
    {
        $permissions = $user->permissions()
            ->where('name', 'like', 'manage % orders')
            ->pluck('name')
            ->map(function ($item) {
                return str_replace('manage ', '', str_replace(' orders', '', $item));
            });

        return $query->whereIn('status', $permissions);
    }
}

所以你可以这样使用它:

$orders = Order::whereAllowedForUser(Auth::user())->paginate(50);

我不是 100% 确定你想用那个 $permissions 查询做什么,我不确定你想做什么,所以再解释一下,我可以帮助你(更好的代码)。

【讨论】:

  • 我使用的是 spatie/laravel-permission,每个用户都有一组权限。其中一些可以根据订单状态管理订单,用户可以有权编辑拒绝和接受的订单,因此他可以“管理拒绝的订单”和“管理接受的订单”。我想显示允许的订单由该用户管理,它是“拒绝和接受”状态
  • 兄弟,您只需复制并粘贴问题中的代码,是的,它可以工作。
  • Laravel 支持自定义构建器,你可以像这样在模型中使用它: public function newEloquentBuilder($query) { return new Builder($query); }
  • 如果你想了解它,这里有一个指南medium.com/@channingdefoe/…
  • 既然可以使用范围查询,为什么还要使用自定义构建器?它甚至不在官方文档中...您使用的是非标准代码...小心...
猜你喜欢
  • 1970-01-01
  • 2022-01-01
  • 2016-09-01
  • 2022-12-29
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
相关资源
最近更新 更多