Reputation: 331
I've been making a query to return all those people who have answered all the questions in a certain block. I've been successfull in getting all the users who answered like this:
public function getUsers()
{
$question_ids = $this->questions->pluck('id');
return User::query()->whereHas('question_answers', function ($query) use ($question_ids) {
$query->whereIn('question_id', $question_ids);
})->get();
}
And I have a function to check if a certain user has answered all the questions in a certain block.
public function hasAnsweredAll(User $user)
{
return (boolean) ($this->questions->count() == $user->question_answers()->whereHas('question', function($query){
$query->where('question_block_id', $this->id);
})->count());
}
Now I get the users I want like the following:
$users=[];
foreach($question_block->getUsers() as $user){
if($question_block->hasAnsweredAll($user)){
$users[] = $user;
}
};
Now my question is, instead of foreach, can I involve my hasAnsweredAll() method in a whereHas() or can I avoid somehow using foreach? I've searched the net for hours now, but no luck, so any help is appreciated.
Upvotes: 0
Views: 44
Reputation: 331
I've managed to work out a solution for my problem. It is so easy, and I've missed this so far when reading the documentations. whereHas() can take an operation and an int as parameters, so it will return instances according to that.
So like this:
public function getUsers()
{
$question_ids = $this->questions->pluck('id');
return User::query()->whereHas('question_answers', function ($query) use ($question_ids) {
$query->whereIn('question_id', $question_ids);
}, '=', $this->questions->count())->get();
}
I don't even need the hasAnsweredAll method anymore, because only users who answered all are returned. So instead the foreach it will look like this:
$users = $question_block->getUsers();
Upvotes: 0
Reputation: 36
You can take a look to this article from Jonathan Reinink, he uses subqueries to solve a problem like the one you mentioned
I hope this works for you
Upvotes: 2