php 47 lines · 8 steps

Streaming a monthly revenue CSV in Laravel

A report service builds a revenue CSV by lazily streaming completed orders, tallying a running total, and writing the file to disk.

Explained by highlit
1<?php
2 
3namespace App\Services\Reports;
4 
5use App\Models\Order;
6use Illuminate\Support\Facades\Storage;
7use League\Csv\Writer;
8 
9class MonthlyRevenueReport
10{
11 public function generate(string $month): string
12 {
13 $path = "reports/revenue-{$month}.csv";
14 $csv = Writer::createFromString();
15 $csv->insertOne(['order_id', 'customer', 'placed_at', 'net_total', 'tax', 'gross_total']);
16 
17 $grossRunningTotal = 0;
18 
19 Order::query()
20 ->whereYear('placed_at', substr($month, 0, 4))
21 ->whereMonth('placed_at', substr($month, 5, 2))
22 ->where('status', 'completed')
23 ->with('customer:id,name')
24 ->orderBy('placed_at')
25 ->lazy(1000)
26 ->each(function (Order $order) use ($csv, &$grossRunningTotal): void {
27 $tax = round($order->net_total * $order->tax_rate, 2);
28 $gross = $order->net_total + $tax;
29 $grossRunningTotal += $gross;
30 
31 $csv->insertOne([
32 $order->id,
33 $order->customer->name,
34 $order->placed_at->toDateTimeString(),
35 number_format($order->net_total, 2, '.', ''),
36 number_format($tax, 2, '.', ''),
37 number_format($gross, 2, '.', ''),
38 ]);
39 });
40 
41 $csv->insertOne(['', '', '', '', 'TOTAL', number_format($grossRunningTotal, 2, '.', '')]);
42 
43 Storage::disk('reports')->put($path, $csv->toString());
44 
45 return $path;
46 }
47}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Lazy collections let you process large query results in chunks without loading every row into memory at once.
  2. 2Accumulating a total by reference inside the iteration callback avoids a second pass over the data.
  3. 3Eager-loading and column selection on relations keep per-row work cheap during a big export.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Streaming a monthly revenue CSV in Laravel — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code