急切负载约束和 whereHas
Posted
技术标签:
【中文标题】急切负载约束和 whereHas【英文标题】:Eager load constraint and whereHas 【发布时间】:2014-04-20 21:23:06 【问题描述】:考虑这个查询:
$query = Ticket::whereHas('user', function($q) use ($search)
$q->where(function($q) use ($search)
$q->where('name', 'LIKE', '%'. $search .'%')->orWhere('username', 'LIKE', '%'. $search .'%');
);
)->paginate(10);
还有这个:
$query = Ticket::with(array('user' => function($q) use ($search)
$q->where('name', 'LIKE', '%'. $search .'%')->orWhere('username', 'LIKE', '%'. $search .'%');
))->paginate(10);
在测试期间,第一个查询在搜索 John 时返回了 50 张票中的 47 张,正如预期的那样。
用第二个查询复制搜索,返回 50 个结果,全部返回。
更准确地说,第二个查询中发生的情况是,当不应该返回的 3 行之一在分页中时,它会在尝试访问诸如 $ticket->user->name
之类的属性时中断。否则,什么都不会中断。
为什么第二个查询会失败?
【问题讨论】:
你想做什么? 我想根据上面的like子句检索属于某个用户的票。 你有一个工作的,第一个。 我对另一个很好奇。 【参考方案1】:在下面给出的第二个中:
$query = Ticket::with(array('user' => function($q) use ($search)
$q->where('name', 'LIKE', '%'. $search .'%')->orWhere('username', 'LIKE', '%'. $search .'%');
))->paginate(10);
你得到所有的票是因为你没有过滤票,例如,这样想查询:
$query = Ticket::with('user')->paginate(10);
你会得到什么,所有有用户的票,但是通过添加一个约束,你只过滤用户而不是票,所以在这种情况下,你的查询将是这样的:
select * from `tickets` where `tickets`.`deleted_at` is null
select * from `users` where `users`.`ticket_id` in (?, ?, ?, ?, ?, ?, ?, ?) and `name` ... ?
因此,首先选择票证时没有任何过滤,然后对于用户,将执行另一个查询,但在第一个查询中执行的是不同的查询。因此,在第二个示例中,由于您的所有票证都没有user
,因此当在不包含相关用户的Ticket
模型上执行$ticket->user->name
时,错误就会出现,因为没有@ 987654327@ 所以没有name
属性。
第一个查询 (whereHas) 可能如下所示:
select * from `tickets` where `tickets`.`deleted_at` is null and (select count(*) from `users` where `users`.`ticket_id` = `tickets`.`id` and `name` LIKE ? ...) >= ?
如果您想查看每个生成的查询,请在所有查询之后使用以下查询:
dd(DB::getQueryLog());
这将返回一个由查询生成器生成并执行的查询数组。
【讨论】:
看DB::getQueryLog()
和你说的一模一样。非常感谢您对这位狼人先生的说明。以上是关于急切负载约束和 whereHas的主要内容,如果未能解决你的问题,请参考以下文章