سؤال

Consider this query:

$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);

And also this one:

$query = Ticket::with(array('user' => function($q) use ($search)
{
    $q->where('name', 'LIKE', '%'. $search .'%')->orWhere('username', 'LIKE', '%'. $search .'%');
}))->paginate(10);

While testing, the first query returns 47 out of 50 tickets in a search for John, as expected.

Replicating the search with the second query, 50 results are returned, all of them.

More precisely what happens in the second query is when one of the not supposed 3 rows to return are among the pagination, then it breaks when trying to access a property such as $ticket->user->name. Otherwise, nothing breaks.

Why would the second query fail?

هل كانت مفيدة؟

المحلول

In the second one which is as given below:

$query = Ticket::with(array('user' => function($q) use ($search) {
    $q->where('name', 'LIKE', '%'. $search .'%')->orWhere('username', 'LIKE', '%'. $search .'%');
}))->paginate(10);

You are getting all tickets because you didn't filter the tickets, for example, think the query like this:

$query = Ticket::with('user')->paginate(10);

What will you get, all the tickets with users but by adding a constraint you are filtering the users only not tickets, so in this case your query would be something like this:

select * from `tickets` where `tickets`.`deleted_at` is null
select * from `users` where `users`.`ticket_id` in (?, ?, ?, ?, ?, ?, ?, ?) and `name` ... ?

So, at first the tickets are getting selected without any filtering and then for the users, another query will be executed but in the first one there is a different query is getting executed. So, in the second example, since all of your tickets don't have a user so when doing $ticket->user->name on a Ticket model which doesn't contain a related user then the error is raising because there is no user so no name property.

The first query (whereHas) may look something like this:

select * from `tickets` where `tickets`.`deleted_at` is null and (select count(*) from `users` where `users`.`ticket_id` = `tickets`.`id` and `name` LIKE ? ...) >= ?

If you want to see what query each of those generated then use following after all of your queries:

dd(DB::getQueryLog());

This will return you an array of queries that was generated by query builder and executed.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top