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