Laravel query model with relations, I just want the related models that meet criteria, how can I do it?

Updated: Feb 04, 2025

Laravel query model with relations, I just want the related models that meet criteria, how can I do it?

To achieve a Laravel query model with relations where you only want the related models that meet specific criteria, you can use Laravel's eager loading and filtering techniques. Eager loading is a method to load the related models with a single query instead of making multiple queries. Filtering can be done using Laravel's query builder or Eloquent methods.

Let's assume we have two models, Post and Comment, where a Post has many Comments. We want to get all the Posts with their related Comments that have a specific status value.

First, let's define the relationships in the models:

// app/Post.php

class Post extends Model
{
    public function comments()
    {
        return $this->hasMany(Comment::class);
    }
}

// app/Comment.php

class Comment extends Model
{
    public function post()
    {
        return $this->belongsTo(Post::class);
    }
}

Now, let's write the query:

// app/Http/Controllers/PostController.php

use App\Post;
use App\Comment;

class PostController extends Controller
{
    public function index()
    {
        $posts = Post::with('comments')
                    ->whereHas('comments', function($query) {
                        $query->where('status', 'published');
                    })
                    ->get();

        return view('posts.index', compact('posts'));
    }
}

In the index method, we use the with method to eagerly load the comments relation for each Post. The whereHas method is used to filter the related Comments based on the given criteria (status = 'published'). Finally, we call the get method to execute the query and retrieve the results.

The resulting $posts collection will contain all the Post instances with their related Comments that meet the given criteria.