雄辩的子查询中的 whereIn 函数不会过滤任何记录

Posted

技术标签:

【中文标题】雄辩的子查询中的 whereIn 函数不会过滤任何记录【英文标题】:whereIn function within a sub query within eloquent doesnt filter any records 【发布时间】:2022-01-13 01:08:44 【问题描述】:

我有一个 Prize、Ticket 和 User 模型。一个奖品可以有多张票,一张票只能与一个用户关联。

每个奖品都有一张中奖券,我想做的是列出我所有拥有中奖券的用户,如下所示:

$winning_tickets = Prize::WinnerSelected()->get('ticket_winner_id')->pluck('ticket_winner_id');

$users = User::with(['tickets' => function($query) use ($winning_tickets) 
     $query->whereIn('id', $winning_tickets);
])->get();

$winning_tickets 返回一组中奖彩票 ID,但 $users 集合返回我的所有用户,甚至是没有彩票记录的用户。

谁能解释我做错了什么?

【问题讨论】:

谢谢,不敢相信我错过了这个。我实际上有其他方法可以做到这一点。你能把它转换成答案吗? 【参考方案1】:

with() 实际上并没有过滤返回的User 集合。为此,您需要使用whereHas():

$winningTickets = Prize::WinnerSelected()->get('ticket_winner_id')->pluck('ticket_winner_id');

$users = User::whereHas('tickets', function($query) use ($winningTickets) 
     $query->whereIn('id', $winningTickets);
)->get();

现在,$users 集合将仅包含具有一个或多个 Ticket 记录与 $winning_tickets 中的给定 ticket_winner_id 匹配的 User 记录。

如果需要,您可以同时使用with()whereHas() 来过滤急切加载关联的Ticket 记录:

$winningTickets = Prize::WinnerSelected()->get('ticket_winner_id')->pluck('ticket_winner_id');

$filterClause = function ($query) use ($winningTickets) 
  return $query->whereIn('id', $winningTickets);
;

$users = User::with(['tickets' => $filterClause])
->whereHas('tickets', $filterClause)
->get();

function ($query) 定义为可重复使用的子句以避免重复,瞧!

旁注,您不需要将->get() 链接到->pluck(); Builder 和 Collection 类都有一个->pluck() 方法,所以这是有效的:

$winningTickets = Prize::WinnerSelected()->pluck('ticket_winner_id');

【讨论】:

以上是关于雄辩的子查询中的 whereIn 函数不会过滤任何记录的主要内容,如果未能解决你的问题,请参考以下文章

Laravel Query Builder 在“whereIn”语句的子查询中使用父查询?

用户为 where in 子句提供的子查询是不是存在注入攻击?

Laravel Eloquent 多对多查询 whereIn

雄辩的关系过滤

Laravel 过滤多个 WhereIn 数组

Laravel 雄辩查询的高级 where