eloquent 子查询中的 whereIn 函数不过滤任何记录

whereIn function within a sub query within eloquent doesnt filter any records

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

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

$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 returns 中奖彩票id数组,但是$users集合 returns ALL my users, even users that have no ticket records.

谁能解释一下我做错了什么?

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 集合将仅包含 User 条记录,这些记录有一条或多条 Ticket 条记录与 $winning_tickets 中给定的 ticket_winner_id 相匹配。

如果需要,您可以同时使用 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');