# Laravel PDF Laravel PDF is a package by Spatie that provides a simple, elegant way to create PDFs in Laravel applications. It supports multiple PDF generation backends through a driver-based architecture: Browsershot (Chromium-based, default), Gotenberg (Docker-based), Cloudflare Browser Rendering API, and DOMPDF (pure PHP). The Chromium-based drivers support modern CSS features like flexbox, grid, and Tailwind CSS, while DOMPDF offers a zero-dependency solution for simpler PDFs. The package integrates seamlessly with Laravel's Blade templating, filesystem abstraction, and queue system. You can render Blade views as PDFs, save them locally or to cloud storage (S3, etc.), return them as HTTP responses, and generate them in background queues. It also includes a comprehensive testing API with fakes and assertions for verifying PDF generation in your test suite. ## Installation Install the package via Composer, then optionally install a driver dependency. ```bash # Install the package composer require spatie/laravel-pdf # For Browsershot driver (default) - requires Node.js and Chrome composer require spatie/browsershot # For DOMPDF driver (pure PHP, no external dependencies) composer require dompdf/dompdf # Publish config file (optional) php artisan vendor:publish --tag=pdf-config ``` ## Creating PDFs from Blade Views Render a Blade view as a PDF and save it to the filesystem. Pass data to the view as the second argument. ```php use Spatie\LaravelPdf\Facades\Pdf; // Basic usage - render view and save Pdf::view('pdf.invoice')->save('/path/to/invoice.pdf'); // Pass data to the view Pdf::view('pdf.invoice', ['invoice' => $invoice, 'customer' => $customer]) ->save('/path/to/invoice.pdf'); // Create PDF from raw HTML Pdf::html('

Hello World

This is a PDF document.

') ->save('/path/to/document.pdf'); ``` ## Returning PDFs as HTTP Responses Return a PDF directly from a controller as an HTTP response. Use the `pdf()` helper or the Facade. ```php use Spatie\LaravelPdf\Facades\Pdf; use function Spatie\LaravelPdf\Support\pdf; class InvoiceController { // Using the helper function - inline display in browser public function show(Invoice $invoice) { return pdf('pdf.invoice', ['invoice' => $invoice]) ->name('invoice-2024.pdf'); } // Force download instead of inline display public function download(Invoice $invoice) { return Pdf::view('pdf.invoice', ['invoice' => $invoice]) ->name('invoice-2024.pdf') ->download(); } } ``` ## Page Format and Orientation Set page size, orientation, and margins using fluent methods. Supports standard formats and custom dimensions. ```php use Spatie\LaravelPdf\Facades\Pdf; use Spatie\LaravelPdf\Enums\Format; use Spatie\LaravelPdf\Enums\Orientation; use Spatie\LaravelPdf\Enums\Unit; Pdf::view('pdf.report', ['data' => $data]) ->format(Format::A4) // Standard format (A4, Letter, Legal, etc.) ->landscape() // Landscape orientation ->margins(20, 15, 20, 15, Unit::Millimeter) // Top, right, bottom, left margins ->save('report.pdf'); // Custom paper size (e.g., for receipts) Pdf::view('pdf.receipt', ['order' => $order]) ->paperSize(80, 200, 'mm') // Width, height, unit ->orientation(Orientation::Portrait) ->save('receipt.pdf'); ``` ## Headers and Footers Add repeating headers and footers to every page. Use Blade views or raw HTML with page number directives. ```php use Spatie\LaravelPdf\Facades\Pdf; Pdf::view('pdf.contract', ['contract' => $contract]) ->headerView('pdf.header', ['company' => $company]) ->footerView('pdf.footer') ->format('a4') ->save('contract.pdf'); // Using raw HTML for header/footer Pdf::view('pdf.invoice', ['invoice' => $invoice]) ->headerHtml('
Company Name
') ->footerHtml('
Page @pageNumber of @totalPages
') ->save('invoice.pdf'); ``` ```blade {{-- resources/views/pdf/footer.blade.php --}} ``` ## Saving to Cloud Storage Disks Save PDFs directly to any Laravel filesystem disk (S3, GCS, etc.) using the `disk()` method. ```php use Spatie\LaravelPdf\Facades\Pdf; // Save to S3 Pdf::view('pdf.invoice', ['invoice' => $invoice]) ->disk('s3') ->save('invoices/invoice-2024-001.pdf'); // Save with custom visibility Pdf::view('pdf.report', ['report' => $report]) ->disk('s3', 'public') ->save('reports/monthly-report.pdf'); ``` ## Queued PDF Generation Generate PDFs in background queues for better performance. Chain callbacks for success/failure handling. ```php use Spatie\LaravelPdf\Facades\Pdf; use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Log; Pdf::view('pdf.invoice', ['invoice' => $invoice]) ->format('a4') ->disk('s3') ->saveQueued('invoices/invoice.pdf') ->onQueue('pdfs') ->onConnection('redis') ->then(function (string $path, ?string $diskName) use ($user) { // PDF generated successfully - send email notification Mail::to($user)->send(new InvoiceReady($path, $diskName)); }) ->catch(function (Throwable $e) { Log::error('PDF generation failed: ' . $e->getMessage()); }); ``` ## PDF Metadata Set document metadata like title, author, and keywords that appear in PDF viewers. ```php use Spatie\LaravelPdf\Facades\Pdf; Pdf::view('pdf.invoice', ['invoice' => $invoice]) ->meta( title: 'Invoice #' . $invoice->number, author: 'Acme Corporation', subject: 'Monthly Invoice', keywords: 'invoice, billing, acme', creator: 'My Laravel App', creationDate: now() ) ->save('invoice.pdf'); ``` ## Advanced Formatting Options Use scale, page ranges, tagged PDFs, and conditional formatting for advanced output control. ```php use Spatie\LaravelPdf\Facades\Pdf; Pdf::view('pdf.report', ['report' => $report]) ->format('a4') ->scale(0.75) // Scale content (0.1 to 2.0) ->pageRanges('1-3, 5, 7-10') // Include specific pages only ->tagged() // Generate accessible/tagged PDF ->save('report.pdf'); // Conditional formatting based on data Pdf::view('pdf.invoice', ['invoice' => $invoice]) ->format('a4') ->when($invoice->isLandscape(), fn ($pdf) => $pdf->landscape()) ->when($invoice->hasLetterhead(), fn ($pdf) => $pdf->headerView('pdf.letterhead')) ->unless($invoice->isCompact(), fn ($pdf) => $pdf->margins(20, 15, 20, 15)) ->save('invoice.pdf'); ``` ## Multi-Page PDFs with Page Breaks Use Blade directives to create multi-page documents with explicit page breaks and page numbers. ```blade {{-- resources/views/pdf/report.blade.php --}}

Executive Summary

{{ $report->summary }}

@pageBreak

Detailed Analysis

@foreach($report->sections as $section)

{{ $section->title }}

{{ $section->content }}

@if(!$loop->last) @pageBreak @endif @endforeach
``` ## Driver Selection and Configuration Switch between PDF drivers globally or per-PDF. Configure via environment variables or at runtime. ```php use Spatie\LaravelPdf\Facades\Pdf; // Use a specific driver for this PDF Pdf::view('pdf.invoice', ['invoice' => $invoice]) ->driver('cloudflare') // 'browsershot', 'cloudflare', 'dompdf', 'gotenberg' ->format('a4') ->save('invoice.pdf'); // Environment configuration (.env) // LARAVEL_PDF_DRIVER=cloudflare // CLOUDFLARE_API_TOKEN=your-token // CLOUDFLARE_ACCOUNT_ID=your-account-id // Or for Gotenberg (Docker-based) // LARAVEL_PDF_DRIVER=gotenberg // GOTENBERG_URL=http://localhost:3000 ``` ## Customizing Browsershot Customize the underlying Browsershot instance for advanced Chrome/Puppeteer options. ```php use Spatie\LaravelPdf\Facades\Pdf; use Spatie\Browsershot\Browsershot; Pdf::view('pdf.invoice', ['invoice' => $invoice]) ->withBrowsershot(function (Browsershot $browsershot) { $browsershot ->scale(0.8) ->setOption('args', ['--disable-web-security']) ->waitUntilNetworkIdle(); }) ->save('invoice.pdf'); // Set Browsershot defaults for all PDFs in a service provider Pdf::default()->withBrowsershot(function (Browsershot $browsershot) { $browsershot->setOption('args', [ '--disable-web-security', '--allow-file-access-from-files', ]); }); ``` ## AWS Lambda PDF Generation Offload PDF generation to AWS Lambda using Sidecar for better performance and scalability. ```php use Spatie\LaravelPdf\Facades\Pdf; // Generate single PDF on Lambda Pdf::view('pdf.invoice', $data) ->onLambda() ->save('invoice.pdf'); // Set Lambda as default for all PDFs (in service provider) Pdf::default()->onLambda(); ``` ## Setting Global Defaults Configure default options for all PDFs in a service provider. ```php use Spatie\LaravelPdf\Facades\Pdf; use Spatie\LaravelPdf\Enums\Format; // In AppServiceProvider::boot() Pdf::default() ->headerView('pdf.default-header') ->footerView('pdf.default-footer') ->format(Format::A4) ->margins(15, 10, 15, 10); // Individual PDFs can still override defaults Pdf::html('

Hello

') ->format(Format::Letter) // Overrides A4 default ->save('document.pdf'); ``` ## Extending with Macros Add custom methods to the PdfBuilder class using Laravel's macro functionality. ```php use Spatie\LaravelPdf\PdfBuilder; // In AppServiceProvider::boot() PdfBuilder::macro('companyInvoice', function (string $invoiceNumber) { return $this ->headerView('pdf.company-header') ->footerHtml('
Invoice ' . $invoiceNumber . '
') ->format('a4'); }); // Usage Pdf::view('pdf.invoice', ['invoice' => $invoice]) ->companyInvoice($invoice->number) ->save('invoice.pdf'); ``` ## Creating Custom Drivers Implement the PdfDriver interface to create custom PDF generation backends. ```php namespace App\Pdf\Drivers; use Spatie\LaravelPdf\Drivers\PdfDriver; use Spatie\LaravelPdf\PdfOptions; class WeasyPrintDriver implements PdfDriver { public function __construct(protected array $config = []) {} public function generatePdf( string $html, ?string $headerHtml, ?string $footerHtml, PdfOptions $options, ): string { // Generate PDF and return content as string $process = Process::run(['weasyprint', '-', '-'], $html); return $process->output(); } public function savePdf( string $html, ?string $headerHtml, ?string $footerHtml, PdfOptions $options, string $path, ): void { file_put_contents($path, $this->generatePdf($html, $headerHtml, $footerHtml, $options)); } } // Register in service provider $this->app->singleton('laravel-pdf.driver.weasyprint', fn () => new WeasyPrintDriver()); // Use the custom driver Pdf::view('invoice')->driver('weasyprint')->save('invoice.pdf'); ``` ## Testing PDFs Use the fake() method to mock PDF generation and make assertions in tests. ```php use Spatie\LaravelPdf\Facades\Pdf; use Spatie\LaravelPdf\PdfBuilder; it('generates an invoice PDF', function () { Pdf::fake(); $invoice = Invoice::factory()->create(); $this->get(route('invoice.download', $invoice))->assertOk(); // Assert PDF was returned as response Pdf::assertRespondedWithPdf(function (PdfBuilder $pdf) use ($invoice) { return $pdf->downloadName === 'invoice.pdf' && $pdf->isDownload() && str_contains($pdf->html, $invoice->number); }); }); it('saves invoice to storage', function () { Pdf::fake(); GenerateInvoice::dispatch($invoice); // Assert PDF was saved to specific path Pdf::assertSaved(function (PdfBuilder $pdf, string $path) { return $path === storage_path('invoices/invoice.pdf') && $pdf->viewName === 'pdf.invoice'; }); }); it('queues PDF generation', function () { Pdf::fake(); QueueInvoice::dispatch($invoice); Pdf::assertQueued(function (PdfBuilder $pdf, string $path) { return $path === 'invoice.pdf' && $pdf->contains('Total'); }); }); // Simple assertion methods Pdf::assertViewIs('pdf.invoice'); Pdf::assertSee('Total: $100.00'); Pdf::assertViewHas('invoice', $invoice); Pdf::assertNotQueued(); ``` ## Using Tailwind CSS Style PDFs with Tailwind CSS using the Chromium-based drivers (Browsershot, Cloudflare, Gotenberg). ```blade {{-- resources/views/pdf/invoice.blade.php --}}

Invoice

#{{ $invoice->number }}
@foreach($invoice->items as $item) @endforeach
Item Amount
{{ $item->name }} ${{ number_format($item->amount, 2) }}
Total: ${{ number_format($invoice->total, 2) }}
``` ## Inline Images in Headers/Footers Use the @inlinedImage directive to embed images in headers and footers. ```blade {{-- resources/views/pdf/header.blade.php --}}
@php $logo = public_path('images/logo.png'); @endphp @inlinedImage($logo) {{ $company->name }}
{{-- Or use a URL --}} @inlinedImage('https://example.com/logo.png') ``` ## Configuration Reference Complete configuration file with all available options. ```php // config/laravel-pdf.php return [ 'driver' => env('LARAVEL_PDF_DRIVER', 'browsershot'), 'browsershot' => [ 'node_binary' => env('LARAVEL_PDF_NODE_BINARY'), 'npm_binary' => env('LARAVEL_PDF_NPM_BINARY'), 'chrome_path' => env('LARAVEL_PDF_CHROME_PATH'), 'node_modules_path' => env('LARAVEL_PDF_NODE_MODULES_PATH'), 'include_path' => env('LARAVEL_PDF_INCLUDE_PATH'), 'bin_path' => env('LARAVEL_PDF_BIN_PATH'), 'temp_path' => env('LARAVEL_PDF_TEMP_PATH'), 'write_options_to_file' => env('LARAVEL_PDF_WRITE_OPTIONS_TO_FILE', false), 'no_sandbox' => env('LARAVEL_PDF_NO_SANDBOX', false), ], 'cloudflare' => [ 'api_token' => env('CLOUDFLARE_API_TOKEN'), 'account_id' => env('CLOUDFLARE_ACCOUNT_ID'), ], 'gotenberg' => [ 'url' => env('GOTENBERG_URL', 'http://localhost:3000'), ], 'dompdf' => [ 'is_remote_enabled' => env('LARAVEL_PDF_DOMPDF_REMOTE_ENABLED', false), 'chroot' => env('LARAVEL_PDF_DOMPDF_CHROOT'), ], 'job' => \Spatie\LaravelPdf\Jobs\GeneratePdfJob::class, ]; ``` Laravel PDF is ideal for generating invoices, reports, contracts, receipts, and any document requiring PDF output in Laravel applications. The driver-based architecture allows you to choose the best backend for your infrastructure - use Browsershot for full CSS support with local Chrome, Cloudflare for serverless deployments, Gotenberg for containerized environments, or DOMPDF for simple PDFs without external dependencies. The package follows Laravel conventions with its fluent API, Blade integration, filesystem abstraction support, and queue compatibility. Combined with the comprehensive testing utilities, it provides a complete solution for PDF generation that scales from simple documents to complex, high-volume PDF workflows. The macroable PdfBuilder class and custom driver support ensure you can extend the package to meet any specialized requirements.