Laravel Eloquent复杂嵌套关联查询逻辑错误排查与优化
修正Laravel Eloquent跨层级或条件查询问题
问题根源
你之前的代码存在两个核心问题:
- 字段归属错误:将
CourseEnrollment的privileges字段放到了关联模型Member的查询闭包里,导致实际查询的是members.privileges而非course_enrollments.privileges - 逻辑结构混乱:
whereHas内部的orWhere没有和邮箱过滤条件正确嵌套,使得邮箱过滤规则被or逻辑覆盖,出现不符合过滤要求的结果
修正后的代码
CourseEnrollment::whereIn('domain_id', $domain_ids) ->where(function ($query) use ($filterUser) { // 条件1:当前课程报名记录的privileges不等于0 $query->where('privileges', '!=', 0) // 条件2:关联的会员是导师,且符合邮箱过滤规则 ->orWhereHas('member', function ($memberQuery) use ($filterUser) { $memberQuery->where('is_mentor', 1); if ($filterUser === 'true') { $memberQuery->where('email', 'NOT LIKE', '%@gmail.com%') ->where('email', 'NOT LIKE', '%@yahoo.com%') ->where('email', 'NOT LIKE', '%@boss.com%') ->where('email', 'NOT LIKE', '%@test.com%'); } }); }) ->get();
代码逻辑说明
- 外层
where()包裹核心或逻辑:确保domain_id过滤是全局生效的,同时将两个核心条件(自身privileges≠0、关联会员符合要求)用or连接 - 条件1直接查询自身字段:直接针对
CourseEnrollment的privileges字段做判断 - 条件2用
orWhereHas()关联会员模型:- 先指定会员必须是导师(
is_mentor=1) - 当开启邮箱过滤时,添加多个
NOT LIKE规则,确保邮箱不在指定域名列表中 - 所有会员相关的过滤规则都嵌套在
orWhereHas的闭包里,只会作用于这个分支,不会干扰其他条件
- 先指定会员必须是导师(
可选优化:邮箱过滤的子查询写法
如果数据量较大,用子查询可以减少重复的NOT LIKE语句,提升查询效率:
if ($filterUser === 'true') { $memberQuery->whereNotIn('email', function ($subQuery) { $subQuery->select('email') ->from('members') ->where(function ($q) { $q->where('email', 'LIKE', '%@gmail.com%') ->orWhere('email', 'LIKE', '%@yahoo.com%') ->orWhere('email', 'LIKE', '%@boss.com%') ->orWhere('email', 'LIKE', '%@test.com%'); }); }); }
内容的提问来源于stack exchange,提问作者Steinie
相关产品推荐
相关产品推荐

