如何过滤 Eloquent 中急切加载的表?

How do I filter on eagerly-loaded tables in Eloquent?

基本上,我希望能够检索用户并快速加载电子邮件地址,然后使用 where 子句限制我引入的用户。

$query = User::with('emails')->whereIn ('user_id', $user_ids);

$query->where('emails.email_address', 'LIKE', "%example%");

$usersWithEmails = $query->get();

这个有效:

$query->where('first_name', 'LIKE', "%test%");

这让我相信 where 子句仅应用于基本用户对象,但我不想获得与该电子邮件不匹配的用户。我知道我可以用几个查询来做到这一点,但这是针对 UI 过滤器的,它们可以在许多子表上进行过滤,所以这样会更好。

我该怎么做?

您可以将 with 参数更改为关联数组,其中键是关系的名称,值是应用任何相关约束的闭包。

$query = User::with(['emails' => function ($query) {
    $query->where('emails.email_address', 'LIKE', '%example%');
}])->whereIn ('user_id', $user_ids);

您可以查看 Eloquent's docs 了解更多信息,这是 "Eager Loading" 中的第一个要点。

如果您需要根据关系过滤用户,您要找的是whereHas

http://laravel.com/docs/5.0/eloquent#querying-relations

User::whereIn('id', [1, 3])->whereHas('emails', function ($query) {
  $query->where('emails.email_address', 'LIKE', '%example%');
})->with('emails');

这将:select id = [1,3] 的用户,然后过滤掉电子邮件模式不匹配的结果,然后加载结果行的关系。

使用 whereHaswith 的区别(Logan 的 示例)是后者将加载除电子邮件字段之外的所有用户 对于预加载模式不匹配的那些,将是 NULL

当然,您可以使用预加载限制然后按空字段过滤集合来完成相同的操作,但我发现这样更干净。我让数据库为我完成工作 =)