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
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Lazy collections let you process large query results in chunks without loading every row into memory at once.
- 2Accumulating a total by reference inside the iteration callback avoids a second pass over the data.
- 3Eager-loading and column selection on relations keep per-row work cheap during a big export.
Related explainers
php
<?php class NameParser {
Parsing a full name into components in PHP
string-parsing
arrays
normalization
Intermediate
8 steps
php
<?php namespace App\Services\Checkout;
Validating coupons with Laravel's Pipeline
pipeline
chain of responsibility
transactions
Intermediate
7 steps
php
<?php namespace App\Services;
How a password strength validator works in PHP
validation
regular-expressions
data-driven
Intermediate
8 steps
ruby
class LogAggregator BUCKET_FORMAT = "%Y-%m-%dT%H:%M" def initialize(entries)
Bucketing log entries by the minute in Ruby
aggregation
hashing
enumerable
Intermediate
5 steps
ruby
class WeeklySignupsReport DEFAULT_WEEKS = 12 def initialize(weeks: DEFAULT_WEEKS, source: User.all)
Building a weekly signups report in Rails
service object
aggregation
group by
Intermediate
7 steps
php
<?php namespace App\Services;
Building a cached daily leaderboard in Laravel
caching
aggregation
eager-loading
Intermediate
9 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/streaming-a-monthly-revenue-csv-in-laravel-explained-php-e60d/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.