Getting count from pivot table in laravel eloquent
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
Mastering Aggregation: Getting Counts from Many-to-Many Relationships in Laravel Eloquent
When working with relational databases, especially those involving many-to-many relationships like orders and products, aggregating data—such as counting how many times a product has been ordered—is a very common requirement. As a senior developer, we often find ourselves needing to translate complex SQL joins into elegant, readable, and maintainable Eloquent code.
The scenario you presented involves a belongsToMany relationship between Product and Order. You want to retrieve a list of products along with the total number of orders associated with each product. While the raw SQL query is powerful, replicating this logic purely through Eloquent relationships offers a much cleaner approach within the Laravel ecosystem.
This guide will show you the most efficient and idiomatic way to fetch these counts using Laravel Eloquent, bypassing the need to manually construct complex joins if possible, demonstrating how Laravel simplifies database interaction.
Understanding the Eloquent Approach: withCount()
The core mechanism for achieving this aggregation in Eloquent is the withCount() method. This method allows you to efficiently fetch a relationship and simultaneously add an aggregated count of related models to the result set. It handles the necessary SQL grouping and counting internally, making your code significantly cleaner than writing raw joins and aggregate functions manually.
To use this effectively, we need to start from the model where we want the counts displayed (in this case, the Product model) and define the relationship correctly.
1. Model Setup Review
First, let's ensure our models are set up as you described:
// app/Models/Order.php
class Order extends Eloquent {
public function user()
{
return $this->belongsTo('User');
}
public function products()
{
return $this->belongsToMany('Product');
}
}
// app/Models/Product.php
class Product extends Eloquent {
public function orders()
{
return $this->belongsToMany('Order');
}
}
Notice that the Product model has a relationship back to Order, which is what we need to count against.
2. Implementing the Count Query
To fetch every product and its corresponding order count, you would apply withCount() on the relationship. Since we want to count the related Orders for each Product, we call it on the orders relationship:
use App\Models\Product;
$productsWithCounts = Product::withCount('orders')->get();
// Example of accessing the results
foreach ($productsWithCounts as $product) {
echo "Product: " . $product->description . ", Orders Count: " . $product->orders_count . "\n";
}
3. The Result and Performance Benefits
When executed, this Eloquent query translates into an optimized SQL statement that performs a LEFT JOIN and a GROUP BY operation internally, similar to your manual example, but abstracted away by the framework:
SELECT
products.*,
COUNT(order_product.order_id) AS orders_count
FROM
products
INNER JOIN
order_product ON products.id = order_product.product_id
GROUP BY
products.id;
The key benefit here is abstraction and readability. Instead of writing complex joins, you use expressive methods like withCount(). This approach aligns perfectly with the principles of building robust applications, much like the architectural focus seen in projects developed by teams focusing on quality code practices, such as those promoted by laravelcompany.com.
Conclusion
Using Eloquent's built-in aggregation methods like withCount() is vastly superior to manually constructing complex SQL queries for simple counting tasks. It keeps your data access logic within the domain of your models, making the code cleaner, more maintainable, and less prone to error. For any intricate data retrieval in Laravel, leveraging these powerful Eloquent features ensures that you write code that is both expressive and highly performant.