Generate PDF Reports in Laravel using Snappy PDF

Summary: Install Snappy and generate dynamic PDF documents in Laravel.


PDF generation is a common feature in web applications, especially for invoice generation, reports, and document downloads. While Laravel provides several libraries to help with PDF creation, Snappy PDF stands out for its simplicity and quality, leveraging the power of the wkhtmltopdf tool to render PDFs from HTML. In this article, we’ll guide you through installing Snappy PDF in your Laravel project and demonstrate how to generate dynamic PDF reports effortlessly.


Why Choose Snappy PDF?

  • High-Quality Rendering: Because Snappy utilizes wkhtmltopdf, your PDFs leverage the full power of a browser engine—complete with CSS, images, and even custom fonts.
  • Easy Integration: Seamless integration with Laravel via the barryvdh/laravel-snappy package.
  • HTML to PDF: Design your reports as blade templates for rapid prototyping and customization.

Step 1: Install wkhtmltopdf

Snappy PDF works as a wrapper for the wkhtmltopdf command-line tool. Before installing the Laravel package, install the binary for your operating system.

Ubuntu / Debian

sudo apt-get install -y wkhtmltopdf

Or download the latest release from wkhtmltopdf.org.

macOS (Homebrew)

brew install Caskroom/cask/wkhtmltopdf

Windows

Download the Windows installer from the official site and add it to your PATH environment variable.


Step 2: Install barryvdh/laravel-snappy

Install the Laravel Snappy package via Composer:

composer require barryvdh/laravel-snappy

Optionally, publish the configuration file:

php artisan vendor:publish --provider="Barryvdh\Snappy\ServiceProvider"

This creates a config/snappy.php file where you can customize binary paths and options.


Step 3: Configuration

Check your config/snappy.php to confirm that it points to your wkhtmltopdf binary. For most systems, the defaults work out-of-the-box.

Example (partial):

'pdf' => [
    'enabled' => true,
    'binary'  => '/usr/local/bin/wkhtmltopdf', // adjust as needed
    'options' => [
        'no-outline', // default options
        'margin-top'    => 10,
        'margin-right'  => 10,
        'margin-bottom' => 10,
        'margin-left'   => 10,
    ],
    'env'     => [],
],

Step 4: Creating a Blade View for Your PDF Report

Create a Blade template to define your PDF content. For example, place this in resources/views/reports/invoice.blade.php:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Invoice #{{ $invoice->id }}</title>
    <style>
        body { font-family: sans-serif; }
        h1   { color: #6366f1; }
        table { border-collapse: collapse; width: 100%; }
        th, td { padding: 8px 12px; border: 1px solid #d1d5db; }
    </style>
</head>
<body>
    <h1>Invoice #{{ $invoice->id }}</h1>
    <p>Date: {{ $invoice->date }}</p>
    <p>Customer: {{ $invoice->customer_name }}</p>

    <table>
        <thead>
            <tr>
                <th>Description</th>
                <th>Quantity</th>
                <th>Price</th>
            </tr>
        </thead>
        <tbody>
            @foreach($invoice->items as $item)
                <tr>
                    <td>{{ $item->description }}</td>
                    <td>{{ $item->quantity }}</td>
                    <td>${{ number_format($item->price, 2) }}</td>
                </tr>
            @endforeach
        </tbody>
    </table>

    <h3>Total: ${{ number_format($invoice->total, 2) }}</h3>
</body>
</html>

Step 5: Generate and Return PDF from a Controller

Use Snappy PDF within your controller to render the Blade view and return the PDF as a download, inline view, or stream.

use Barryvdh\DomPDF\Facade\Pdf; // For DomPDF
use Barryvdh\Snappy\Facades\SnappyPdf; // For Snappy

public function downloadInvoice($id)
{
    $invoice = Invoice::with('items')->findOrFail($id);

    $pdf = SnappyPdf::loadView('reports.invoice', compact('invoice'));

    // Download the PDF
    return $pdf->download("invoice-{$invoice->id}.pdf");

    // Or to stream in browser:
    // return $pdf->stream("invoice-{$invoice->id}.pdf");
}

Note: Make sure to import the correct facade: Barryvdh\Snappy\Facades\SnappyPdf (not Barryvdh\DomPDF\Facade\Pdf).

You can pass data to your views just like any Laravel Blade template, and Snappy will convert the final rendered HTML into a beautiful PDF.


Step 6: Advanced Options

Snappy exposes several handy methods for customizing your report generation:

  • Set Paper Size:

    $pdf->setPaper('a4')->setOrientation('landscape');
    
  • Set PDF Options:

    $pdf->setOption('footer-center', 'Page [page] of [toPage]');
    
  • Save the PDF File:

    $pdf->save(storage_path("invoices/invoice-{$invoice->id}.pdf"));
    

For more available options, check the wkhtmltopdf documentation and the barryvdh/laravel-snappy README.


Troubleshooting

  • Blank or Corrupted PDFs:
    Ensure wkhtmltopdf is installed correctly and the binary path is set in config/snappy.php.
  • Asset Loading Issues:
    Use absolute paths or inline styles. For images, try embedding using public_path() or base64 encoding.
  • Font Rendering:
    Confirm the fonts are accessible to wkhtmltopdf and use web-safe or embedded fonts when possible.

Conclusion

Snappy PDF makes PDF generation in Laravel seamless by letting you render blade templates into high-fidelity PDF documents. Whether you're building invoices, tickets, certificates, or full reports, Snappy lets you leverage your existing Laravel skills and HTML design prowess. With minimal configuration, robust customization, and reliable output, it’s an essential tool for any Laravel developer needing dynamic document generation.


Further Reading: