Laravel: Count number of rows in a relationship
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
Laravel: Efficiently Counting Rows in Complex Eloquent Relationships
As developers working with relational databases through an ORM like Eloquent, performance is paramount. When dealing with nested relationships, especially those involving multiple levels (hasManyThrough), the temptation is often to load all related data and perform the counting in PHP. While this works for small datasets, it quickly becomes an anti-pattern that cripples performance on larger applications.
This post addresses a common challenge: how to efficiently determine the total count of deeply nested relationships without resorting to slow, manual iteration in your application layer. We will look at your specific scenario and demonstrate the highly optimized Eloquent solution.
The Performance Pitfall of Iteration
You have defined a complex relationship structure:
- A
Venuehas manyOffers. - An
Offerhas manyOrders. - You use
hasManyThroughto linkVenues directly toOrders via the intermediateOffertable.
Your initial approach involved fetching all relevant venues and then looping through them in PHP to manually count their associated orders:
$venues = Venue::where('location_id', 5)->with('orders')->get();
$numberOfOrders = 0;
foreach($venues as $venue) {
// This forces N separate queries (or heavy processing) in the loop
$numberOfOrders += $venue->orders->count();
}
As you correctly identified, this method is highly inefficient. For every venue retrieved, Eloquent has to execute an additional query (or a complex join) to count the related orders. If you retrieve 100 venues, you end up executing 101 database queries, leading to significant latency and poor scalability.
The Eloquent Solution: Leveraging Database Aggregation
The key to solving this efficiently is to delegate the counting operation directly to the database using SQL aggregation functions (COUNT()). Instead of loading the data and counting it in PHP, we instruct Eloquent to perform the counting within the initial query.
For relationships where you need a count per parent record, the withCount() method is the most idiomatic and powerful tool in Eloquent. It tells the database to execute a separate, optimized COUNT query for each group defined by the relationship.
Implementing the Efficient Count
To achieve your goal—determining the total number of orders for venues where location_id = 5—you can combine filtering with eager loading and counting:
$totalOrders = Venue::where('location_id', 5)
->withCount('orders') // Eager load and count the related 'orders' relationship
->get();
// Now, $totalOrders collection contains venues, and each venue object
// has a 'orders_count' attribute populated by the database.
// If you only need the grand total across all filtered venues:
$grandTotal = $totalOrders->sum('orders_count');
dump($grandTotal); // Output the single aggregated number directly from the DB
Deeper Dive into withCount()
When using hasManyThrough, the relationship being counted (orders in this case) is defined through the intermediate model. Eloquent intelligently handles the necessary joins and grouping required by the underlying SQL, ensuring that the aggregation happens at the database level rather than in PHP memory. This adheres to the principle of keeping data manipulation close to the data source, which is a core tenet of robust ORM usage, much like the principles behind frameworks such as Laravel.
By using withCount('orders'), you are telling Laravel: "For every venue matching this criteria, calculate the count of its related orders and attach that number to the result set." This results in a single, highly optimized SQL query rather than multiple round trips.
Conclusion
The difference between an inefficient loop and an efficient database operation is the difference between O(N*M) complexity and highly optimized SQL execution. Never rely on manual iteration over loaded Eloquent models for aggregation if the database can perform that calculation faster.
By mastering methods like withCount(), you ensure your Laravel applications remain fast, scalable, and maintainable. Always prioritize letting the database handle the heavy lifting!