Problem: You have a collection of items and need to organize them into groups based on a specific attribute, like grouping users by role or products by category.
Solution:
// Basic groupBy
$users = collect([
['name' => 'John', 'role' => 'admin', 'city' => 'NYC'],
['name' => 'Jane', 'role' => 'user', 'city' => 'LA'],
['name' => 'Bob', 'role' => 'admin', 'city' => 'NYC'],
['name' => 'Alice', 'role' => 'user', 'city' => 'NYC']
]);
$byRole = $users->groupBy('role');
// Result:
// [
// 'admin' => [['name' => 'John'...], ['name' => 'Bob'...]],
// 'user' => [['name' => 'Jane'...], ['name' => 'Alice'...]]
// ]
// Group by nested attribute
$byCity = $users->groupBy('address.city');
// Group by multiple levels
$grouped = $users->groupBy(['role', 'city']);
// Result: nested groups - first by role, then by city
// Custom grouping logic
$byNameLength = $users->groupBy(function ($user) {
return strlen($user['name']);
});
// From database query
$orders = Order::with('customer')
->get()
->groupBy('status');
$ordersByMonth = Order::get()->groupBy(function ($order) {
return $order->created_at->format('Y-m');
});
// Preserve keys after grouping
$products = Product::all()
->groupBy('category_id')
->map(function ($group) {
return $group->sum('price');
});
// Group and count
$userCounts = User::all()
->groupBy('role')
->map->count();
Why it works: groupBy()
creates a new collection where items are organized by the specified key. The original items remain unchanged, just reorganized. When using a callback, you can create custom grouping logic based on any criteria.
Performance tip: For large datasets from the database, consider using SQL GROUP BY with aggregates instead of collection grouping.
Table Of Contents
Related Topics
- How to Filter a Collection Based on a Key's Value - Filter groups after grouping
Share this article
Add Comment
No comments yet. Be the first to comment!