渴望加载约束和whereHas

时间:2014-04-20 21:23:06

标签: php sql laravel eloquent

考虑这个问题:

$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个结果,所有这些结果。

更确切地说,在第二个查询中发生的事情是,当要返回的其中一个不应该返回的行在分页中时,它会在尝试访问$ticket->user->name等属性时中断。否则,什么都没有。

为什么第二个查询会失败?

1 个答案:

答案 0 :(得分:0)

在第二个中,如下所示:

$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->user->name模型上执行Ticket并且不包含相关用户时然后错误正在提高,因为没有user所以没有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());

这将返回由查询构建器生成并执行的查询数组。