3
votes

I'd like to find Project::with('tasks.tags')->get();

where only projects with a particular id of tag return in the result set.

For ex. I'd like to find a project with tasks and tasks with tags with only id of 1. In other words, filter the tasks return inside of the Project - Task relationship.

I have tried various ways but have failed so far.

I have tried:

$project = Project::with('tasks.tags')->whereHas('tasks', function($query){
            $query->whereHas('tags', function($query) {
                $query->where('id', 1);
            });
})->get();

And:

$project = Project::with('tasks.tags')->whereHas('tasks', function($query){
            $query->whereHas('tags', function($query) {
                $query->where('tag_id', 1);
            });
})->get();

This is how the relationships are setup:

In Project.php

public function tasks()
{
    return $this->hasMany(Task::class, 'project_id')->setEagerLoads([]);
}

In Task.php

public function tags()
{
        return $this->morphToMany(Tag::class, 'taggable')->setEagerLoads([]);

}

Note that relationship between Task and Tags is of morphToMany.

Any pointers?

2
Is there a reason you force eager loads to be unset in your relationship definitions?Namoshek
Yes. The Tag class Task class are set as nested tree and I had to load their children recursively. Adding $with = ['children'] allowed me to easily load their children. If I do this manually, I have load 'children' recursively manually for each Task and Tag returned as children as well.stirredo
Okay, makes sense. Did you try your first example with hard coded ids or with variables?Namoshek
Hey, can you check the description again. Made some edit. I'd like to find all projects with a particular tag. I accidentally asked the wrong thing. I have been stuck on this problem for a few hours now and my head isn't right :Dstirredo
It doesn't through any error at all. The query just doesn't filter the tasks at all. What I'd like to do is filter the project's Task with only Tag of a particular ID. Say 1.stirredo

2 Answers

5
votes

You would need to scope the eager loading as well. Something like the following should work:

$project = Project::with(['tasks.tags' => function ($query) {
    $query->where('id', 1);
}])->whereHas('tasks', function ($query) {
    $query->whereHas('tags', function ($query) {
        $query->where('id', 1);
    });
})->get();
5
votes

Found the answer over here.

Project::with(['tasks' => function($q) {
            $q->whereHas('tags', function($query) {
                $query->where('tag_id', 1);
            });
}])->get();