Urudin
Urudin

Reputation: 331

Making a query including model's method

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

Answers (2)

Urudin
Urudin

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

sepaz91
sepaz91

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

Related Questions