首页 > 解决方案 > Laravel 通过 whereNotIn 过滤 whereIn

问题描述

我正在创建一个查询范围来检索一些数据。

我们希望在 include_ids[1,2,3]存在的地方获得结果,但如果模型也是 exclude_ids 的一部分,则过滤它们[4,5]

如果用户订阅了 2 和 4,则不应选择他们。但是,应选择订阅 1,2 或 3 而不是 4,5 的用户。

我已经搞砸了一段时间,它应该看起来像这样

  1. 将所有内容包装在 where 语句中
  2. 加载与另一个模型存在关系的数据
  3. 获取 incl_ids 存在的关系的数据
  4. 如何通过 excl_ids 过滤点 3?

也许我们应该循环 excl_ids 并且当 excl_id 为真时不加载数据?

    public function scopeLoadExcept ($query, $incl_ids, $excl_ids)
    {
        return $query->where(function ($q) use ($incl_ids, $excl_ids) {
            return $q->whereHas('relationship', function ($qq) use ($incl_ids, $excl_ids) {
                return $qq->whereIn('foreign_id', $incl_ids)->where(function ($qqq) use ($excl_ids) {
                    return $qqq->whereNotIn('foreign_id', $excl_ids); // filter this
                });
            });
        });
    }

标签: laraveleloquent

解决方案


你应该使用whereDoesntHave方法

public function scopeLoadExcept($query, $incl_ids, $excl_ids)
{
    return $query->where(
        function ($q) use ($incl_ids, $excl_ids) {
            return $q->whereHas(
                'relationship',
                function ($qq) use ($incl_ids, $excl_ids) {
                    return $qq->whereIn('foreign_id', $incl_ids);
                }
            )->whereDoesntHave(
                'relationship',
                function ($qq) use ($incl_ids, $excl_ids) {
                    return $qq->whereIn('foreign_id', $excl_ids);
                }
            );
        }
    );
}

实际上你不需要使用 where 参数分组,如下所示:

public function scopeLoadExcept($query, $incl_ids, $excl_ids)
{
    return $query->whereHas(
        'relationship',
        function ($qq) use ($incl_ids) {
            return $qq->whereIn('foreign_id', $incl_ids);
        }
    )->whereDoesntHave(
        'relationship',
        function ($qq) use ($excl_ids) {
            return $qq->whereIn('foreign_id', $excl_ids);
        }
    );
}

推荐阅读