Eloquent: Counting Records Based on a Condition (6 Techniques)

Updated: January 17, 2024 By: Guest Contributor Post a comment

Introduction

When using Laravel’s Eloquent ORM, one often encounters scenarios where it’s required to count records in a database table based on specific conditions. This allows developers to easily gather insights about data and perform the necessary logic within the application. We’ll explore how to count records conditionally using Laravel’s Eloquent.

Getting Started

Before diving into conditional counts, ensure that you’ve set up a Laravel project and have Eloquent models to work with. In this tutorial, we will use a simple Post model to represent blog posts in a database.

use App\Models\Post;

// Assuming a Post model already exists

Let’s review some key techniques to count records based on a condition in Eloquent.

Basic Count

The most straightforward approach to count records is using the count() method.


// Count all posts
$postCount = Post::count();

Let’s say we want to count only published posts. This entails adding a conditional within the query.


// Count published posts
$publishedCount = Post::where('status', 'published')->count();

Conditional Counts with Builder Methods

Conditions can be added to Eloquent queries using builder methods:


// Count posts with more than 100 likes
$popularPostsCount = Post::where('likes', '>', 100)->count();

In the above query, where() is used to add a ‘greater than’ conditional.

Counting Related Records

Often, we need to count records that have a certain relationship with another model. Let’s use Comment as a related model:


$commentsCount = Post::withCount('comments')->get();
$commentsCount = $commentsCount->map(function ($item) {
    return $item->comments_count;
});

The withCount() method will add a ‘comments_count‘ attribute to each instance of the Post model retrieved.

You can also apply conditions to the withCount() method like this:


// Count comments that are flagged
$postsWithFlaggedComments = Post::withCount(['comments' => function ($query) {
    $query->where('flagged', true);
}])->get();

Dynamically Accessing Aggregate Properties

With Eloquent, it’s possible to count records dynamically using virtual properties:


// Eloquent Model - Dynamic properties

$posts = Post::all();

foreach ($posts as $post) {
    echo $post->where('status', 'published')->count();
}

Aggregates on Relations

When working with relations, aditional conditions on aggregates can be very helpful:


// Count of related comments that are not flagged
$postWithNonFlaggedComments = Post::withCount(['comments' => function ($query) {
    $query->where('flagged', false);
}])->get();

It’s important not to confuse the withCount() method with loadCount(), which eager loads the relationship counts onto an existing model instance.

You might want to take different actions based on the count:


$post = Post::find(1);

if ($post->comments()->where('flagged', true)->count() > 5) {
    // Take action if there are more than 5 flagged comments on the post
}

Advanced Usage

For advanced usage, Eloquent allows grouping statistics by a certain field. For instance:


$postsByYear = Post::query()
    ->selectRaw('YEAR(created_at) as year')
    ->selectRaw('COUNT(*) as total')
    ->groupBy('year')
    ->get();

In the sample above, we’re grouping posts by year and counting them.

Conclusion

This tutorial introduced various approaches to counting records based on different conditions using Eloquent in a Laravel application. Understanding how to apply these methods effectively is crucial in building efficient Laravel applications that handle data operations with ease.

It’s important to use these methods appropriately, considering the performance of your application when working with large datasets. Leveraging database indexes and optimized SQL queries is crucial to maintain a high-performing application.

By grasping the power of Eloquent, developers can construct complex queries in a more reader-friendly way compared to raw SQL, making the development process both more efficient and enjoyable.