Another common way to use grouping is done by collections. This way, you don't have to do any database queries and just group already-fetched data. For example:
Our database currently looks like this:
And we get our data by a simple query:
$orders = Order::query() ->with(['products,' 'user']) ->get();
Now, we can display the orders table as usual, but we have a requirement to group orders by week. So, we will do it like this:
Controller
$orders = Order::query() ->with(['products', 'user']) ->get(); $orders = $orders ->groupBy(function (Order $order) { // We are using Carbon to parse the date and get the start of the week for our group return Carbon::parse($order->order_time)->startOfWeek()->format('Y-m-d'); }) // As a last step, we will sort the keys in descending order ->sortKeysDesc(); return view('orders.by-week', [ 'orders' => $orders,]);
Using our grouped entries in a view is very simple - just two foreach loops:
View
@foreach($orders as $week => $ordersList) <h2 class="text-2xl font-bold mb-2">{{ $week }}</h2> <table class="table-auto w-full mt-4 mb-4"> <thead> <tr> <th class="px-4 py-2">#</th> <th class="px-4 py-2">User</th> <th class="px-4 py-2">Order time</th> <th class="px-4 py-2">Delivery time</th> <th class="px-4 py-2">Total</th> </tr> </thead> <tbody> @foreach($ordersList as $order) <tr> <td class="border px-4 py-2">{{ $order->id }}</td> <td class="border px-4 py-2">{{ $order->user->name }}</td> <td class="border px-4 py-2">{{ $order->order_time }}</td> <td class="border px-4 py-2">{{ $order->delivery_time }}</td> <td class="border px-4 py-2">${{ number_format($order->total, 2) }}</td> </tr> @endforeach </tbody> </table>@endforeach
This runs a straightforward query on the database:
select * from `orders`
And the result is:
Warning: Doing such transformations on the collection level can be slow and even crash your application if you have a lot of data. So, be careful when doing this, and always test it with a lot of data.