php
57 lines · 9 steps
Rendering invoice PDFs in a Laravel queue job
A queued job that loads an invoice, renders it to PDF, stores the file, and notifies the customer — with retries and failure handling.
Explained by
highlit
1<?php
2
3namespace App\Jobs;
4
5use App\Models\Invoice;
6use App\Notifications\InvoiceGenerated;
7use Barryvdh\DomPDF\Facade\Pdf;
8use Illuminate\Bus\Queueable;
9use Illuminate\Contracts\Queue\ShouldQueue;
10use Illuminate\Foundation\Bus\Dispatchable;
11use Illuminate\Queue\InteractsWithQueue;
12use Illuminate\Queue\SerializesModels;
13use Illuminate\Support\Facades\Storage;
14
15class GenerateInvoicePdf implements ShouldQueue
16{
17 use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
18
19 public int $tries = 3;
20 public int $backoff = 30;
21
22 public function __construct(public Invoice $invoice)
23 {
24 }
25
26 public function handle(): void
27 {
28 $this->invoice->loadMissing(['customer', 'lineItems']);
29
30 $pdf = Pdf::loadView('invoices.pdf', [
31 'invoice' => $this->invoice,
32 'customer' => $this->invoice->customer,
33 'lineItems' => $this->invoice->lineItems,
34 ])->setPaper('a4');
35
36 $path = sprintf('invoices/%s/%s.pdf', $this->invoice->customer_id, $this->invoice->number);
37
38 Storage::disk('invoices')->put($path, $pdf->output(), 'private');
39
40 $this->invoice->update([
41 'pdf_path' => $path,
42 'generated_at' => now(),
43 ]);
44
45 $this->invoice->customer->notify(new InvoiceGenerated($this->invoice));
46 }
47
48 public function uniqueId(): string
49 {
50 return (string) $this->invoice->id;
51 }
52
53 public function failed(\Throwable $e): void
54 {
55 $this->invoice->update(['generation_failed_at' => now()]);
56 }
57}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Implementing ShouldQueue lets heavy work like PDF rendering run in the background instead of blocking the request.
- 2Setting $tries and $backoff plus a failed() hook makes a job resilient to transient errors and observable when it gives up.
- 3Persisting the file path and a timestamp on the model keeps a durable record of what the job produced.
Related explainers
php
<?php namespace App\Http\Requests\DataObjects;
Typed request DTOs in Laravel
data-transfer-object
validation
immutability
Intermediate
6 steps
php
<?php namespace App\Services;
Building a valid iCalendar feed in PHP in Laravel
ical
serialization
formatting
Intermediate
8 steps
php
<?php namespace App\View\Components;
Building a breadcrumb component in Laravel
blade components
url parsing
string manipulation
Intermediate
8 steps
php
<?php namespace App\Experiments;
Weighted random selection in PHP
weighted-random
cumulative-sum
sampling
Intermediate
8 steps
php
final class FieldEncryptor { private string $key;
Authenticated field encryption with libsodium
encryption
libsodium
authenticated-encryption
Intermediate
7 steps
php
<?php final class MarkdownParser {
Building a small Markdown-to-HTML parser in PHP
state-machine
parsing
closures
Intermediate
10 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/rendering-invoice-pdfs-in-a-laravel-queue-job-explained-php-5b11/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.