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