← Other topics

Generate PDFs in Laravel

Video Notes

To generate PDFs in Laravel, we can use the package barryvdh/laravel-dompdf. This package allows you to convert Blade View files into PDFs that can either be displayed directly in the browser or downloaded.

To demonstrate, we’ll generate a simple PDF invoice:

Import package

Import the barryvdh/laravel-dompdf into our Laravel project:

> composer require barryvdh/laravel-dompdf

Routes

/routes/web.php:

<?php
use Illuminate\Support\Facades\Route;

use App\Http\Controllers\InvoiceController;

Route::get('/invoice', [InvoiceController::class, 'generate']);

Controller

/App/Http/Controllers/InvoiceController.php:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Barryvdh\DomPDF\Facade\Pdf;

class InvoiceController extends Controller
{
    public function generate(Request $request)
    {
        $data = [
            'to' => 'Sam Example',
            'subtotal' => '5.00',
            'tax' => '.35',
            'total' => '5.35'
        ];

        $pdf = Pdf::loadView('invoice', $data);

        # Option 1) Show the PDF in the browser
        return $pdf->stream();

        # Option 2) Download the PDF
        // return $pdf->download('invoice.pdf');
    }
}

View

/resources/views/invoice.blade.php:

<!doctype html>
<html lang='en'>

<head>
    <title>Invoice for {{ $to }}</title>
    <meta charset='utf-8'>

    {{-- Use an absolute path when specifying the CSS so it works in the PDF --}}
    <link href='{{ public_path('css/invoice.css') }}' rel='stylesheet'>
</head>

<body>
    <h1>Invoice</h1>
    <img src='images/invoice.png' class='invoice-icon' alt='Invoice icon'>
    <p><span class='label'>Billed to:</span> {{ $to }}</p>
    <p><span class='label'>Subtotal:</span> ${{ $subtotal }}</p>
    <p><span class='label'>Tax:</span> ${{ $tax }}</p>
    <p><span class='label'>Total:</span> ${{ $total }}</p>
</body>

</html>

CSS

/public/css/invoice.css:

.invoice-icon {
    width:100px
}

.label {
    font-weight:bold;
    font-family:Arial, Helvetica, sans-serif;
}

Add a preview mode

When working with PDFs I like to add a “preview” mode I can use during development that lets me quickly load the View in the browser instead of generating the PDF. This saves time, especially if you’re making a lot of edits to your layout/design/content.

The preview mode is activated by adding the query string ?preview to the URL, e.g. https://demo.com.test/invoice?preview.

Here’s the updated controller with preview mode added:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Barryvdh\DomPDF\Facade\Pdf;

class InvoiceController extends Controller
{
    public function generate(Request $request)
    {
        $data = [
            'to' => 'Sam Example',
            'subtotal' => '5.00',
            'tax' => '.35',
            'total' => '5.35'
        ];

        # Optional: Append ?preview to the URL to preview the output directly in the browser instead of downloading the PDF
        if($request->has('preview')) {
            $data['css'] = 'css/invoice.css';
            return view('invoice', $data);
        } else {
            $data['css'] = public_path('css/invoice.css');
        }

        $pdf = Pdf::loadView('invoice', $data);

        # Option 1) Show the PDF in the browser
        return $pdf->stream();

        # Option 2) Download the PDF
        // return $pdf->download('invoice.pdf');
    }
}

Observe that in the above code we dynamically set the path of the CSS depending on whether we’re loading the invoice as a regular View (where we need a relative path) or as a PDF (where we need an absolute path). To accommodate this, update your View so the CSS links like this:

<link href='{{ $css }}' rel='stylesheet'>

Result: Demonstrating preview mode for generating PDFs in Laravel

If this info helped you out, toss a coin in the tip jar?
← Other topics