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

Walkthrough

Space play ←→ step click any line
Three takeaways
  1. 1Implementing ShouldQueue lets heavy work like PDF rendering run in the background instead of blocking the request.
  2. 2Setting $tries and $backoff plus a failed() hook makes a job resilient to transient errors and observable when it gives up.
  3. 3Persisting the file path and a timestamp on the model keeps a durable record of what the job produced.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Rendering invoice PDFs in a Laravel queue job — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code