Laravel Eloquent withCount helps you avoid N+1 issues when counting related models. Learn how to use it to boost your database performance today.
I remember the first time I built a dashboard listing authors and their total book counts. I naively looped through the collection in my Blade template, calling $author->books()->count() for every single row. My local machine didn't blink, but once we deployed to staging with a few hundred records, the page load time spiked to over 2 seconds. That’s the classic N+1 trap.
If you’re still counting related records inside your loops, you’re hitting the database far more often than necessary. Today, we’re going to fix that using withCount.
The withCount method is a built-in feature of Laravel Eloquent that allows you to retrieve the count of a related model without loading the entire relationship collection into memory. Instead of fetching every related object, it adds a subquery to your main query that calculates the count at the database level.
If you are new to how models interact, I suggest brushing up on Eloquent basics: models, relationships, and your first queries before diving into these optimizations.
Let’s look at the difference between the "wrong" way and the "right" way. Suppose you have an Author model that has many Book models.
The inefficient approach:
PHP#6A9955">// Controller $authors = Author::all(); #6A9955">// Blade @foreach ($authors as $author) {{ $author->name }} - {{ $author->books->count() }} @endforeach
This triggers one query to get all authors and then one additional query for every author to count their books. If you have 50 authors, that’s 51 database queries.
The efficient approach:
PHP#6A9955">// Controller $authors = Author::withCount('books')->get(); #6A9955">// Blade @foreach ($authors as $author) {{ $author->name }} - {{ $author->books_count }} @endforeach
Now, Laravel executes exactly two queries: one for the authors and one to count the books. By using withCount, the count is automatically appended to your model as a property named books_count. This approach is critical for Eliminating N+1 queries in Eloquent: A Pragmatic Approach and keeping your application responsive.
Sometimes, you don't want the total count. Maybe you only want to count books published after a certain year. withCount allows you to pass an array or use a closure to handle more complex logic.
PHP$authors = Author::withCount(['books' => function ($query) { $query->where('published_at', '>=', now()->subYears(5)); }])->get();
In this case, the attribute on the model will be named books_count by default. If you need a custom name, you can alias it:
PHP$authors = Author::withCount('books as recent_books_count')->get();
Using withCount is a massive win for performance optimization. Because the database handles the aggregation, you’re transferring significantly less data between the database and your application. I’ve seen this reduce query execution time from around 300ms down to roughly 40ms in scenarios with complex joins.
If you find yourself needing to filter the authors based on these counts, remember that withCount doesn't automatically add a WHERE clause. You’ll need to pair it with other methods. For instance, Mastering Laravel whereHas: Filter Models by Relationship Presence is the tool you want when you need to filter the result set based on whether a relationship exists.
[relationship]_count. If your relationship method is myBooks(), the attribute will be my_books_count.withCount is efficient, if the relationship table doesn't have proper indexes on the foreign key, your database will still struggle. Always ensure your migration includes an index on the foreign key column to keep your Laravel Eloquent queries snappy.withCount if you actually need to display the book titles or other attributes from the related models. In that case, use with() to eager load the relationships instead.Can I use withCount on multiple relationships at once?
Yes. You can pass an array: Author::withCount(['books', 'awards'])->get();. This will give you both books_count and awards_count.
Does withCount work with polymorphic relationships? It does! It works exactly the same way as standard hasMany or belongsToMany relationships.
What if I need the count in a specific order?
You can use orderBy('books_count', 'desc') right after your withCount call to sort your main model results by the count.
I’m still experimenting with how withCount interacts with complex, nested eager loads. It can sometimes lead to unexpected query complexity if you're not careful. If you’re pushing the limits of your database, keep an eye on your query logs—tools like Laravel Debugbar are invaluable here. Don't be afraid to run an EXPLAIN on your generated SQL if things feel slow.
Master the Laravel Query Builder to execute high-performance database queries without the overhead of Eloquent models. Learn how to optimize your PHP apps.