Download or Preview PDF of HTML in Laravel 9 with DOMPDF

In this guide, you will learn how to generate PDF files dynamically from HTML view in the Laravel application by leveraging the DomPDF package module.

We will walk through easy steps to easily configure the PDF file layout or control over if a PDF file needs to be downloaded or just previewed in a new tab of the browser.

PDF files are a portable solution to keep the importation handy or easily share to anybody by any means.

The best part is that we are converting already designed HTML into PDF file, so we don’t need to worry about layout we will be getting the generated PDF files.

To introduce the dynamic building of the PDF files, we will also populate data into the database to create the PDF. In this way, you will also get an idea of how we can easily create data, by creating Models, Factories and Seeders from the Laravel application itself.

Let’s get started!

 

Step 1: Setup Laravel Application

First, we will set up a Laravel project if you haven’t already. We can easily create a new Laravel project using Composer:

composer create-project laravel/laravel laravel-pdf-generator --prefer-dist
cd laravel-pdf-generator

The --prefer-dist flag tells Composer to prefer downloading pre-compiled, distribution (dist) versions of packages instead of source code versions when they are available. It helps in faster installation, takes less disk space and avoids compilation.

 

Step 2: Install a PDF Generation Library

To create PDF in Laravel, we will need a library like dompdf or mpdf. But in this guide, we will use dompdf and install it via Composer by executing the below command:

composer require barryvdh/laravel-dompdf

 

Step 3: Configure the PDF Generator

After the library is installed, we will configure the providers and aliases arrays inside the config/app.php file:

'providers' => [
    // ...
    Barryvdh\DomPDF\ServiceProvider::class,
],
'aliases' => [
    // ...
    'PDF' => Barryvdh\DomPDF\Facade::class,
],

Next, publish the configuration file:

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

This will create a config/dompdf.php file where we can easily configure PDF options like paper size, orientation, and more for example:

// File: config/dompdf.php

return [
    // Other configurations...

    'options' => [
        // Other settings...
        
        'default_paper_size' => 'A4',           // Change the default paper size
        'default_paper_orientation' => 'landscape', // Change the default paper orientation
        
        'margin_top' => 10,     // Change the top margin in millimeters
        'margin_right' => 20,   // Change the right margin in millimeters
        'margin_bottom' => 10,  // Change the bottom margin in millimeters
        'margin_left' => 20,    // Change the left margin in millimeters
        
        // Other settings...
    ],

    // Other configurations...
];

 

Step 3: Add Route

Now, we will define two routes for our application, one will fetch all the Datatable rows (We will set up database data in upcoming sections) and populate on blade view and the other will download the HTML view as PDF files.

Open the routes/web.php file and add the following route definition:

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\BookController;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', [BookController::class, 'showBooks']);
Route::get('/generate-pdf', [BookController::class, 'generatePDF']);

 

Step 4: Add Controller

Thereafter, we will create a controller to fetch all the data and handle the PDF generation logic. Run the following command to generate a controller named BookController:

php artisan make:controller BookController

It will create the controller at this location app/Http/Controllers/BookController.php. Update the file as below:

<?php
namespace App\Http\Controllers;
use App\Models\Book;

class BookController extends Controller
{
    // Show/ Fetch all books data
    public function showBooks()
    {
        $books = Book::all();
        return view('books', compact('books'));
    }

    // Fetch all table rows, convert view into PDF and Download
    public function generatePDF()
    {
        $books = Book::all();
        $pdf = \Barryvdh\DomPDF\Facade\Pdf::loadView('books', compact('books'));

        // Download the PDF with a specific file name
        return $pdf->download('book_list.pdf');
    }
}

 

Step 5: Create a View File

Now, create a Blade view that will serve as the template HTML for your PDF. At this path resources/views, create a file named books.blade.php and update it as shown below:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
</head>
<body>
    <div class="container mt-5">
        <h2 class="text-center mb-3">Generate Dynamic PDF in Laravel - FreakyJolly.com</h2>
        <div class="d-flex justify-content-end mb-4">
            <a class="btn btn-primary" href="{{ URL::to('generate-pdf') }}">Export to PDF</a> <!-- Link to export PDF -->
        </div>
        <table class="table table-bordered mb-5">
            <thead>
                <tr class="thead-dark">
                    <th scope="col">#</th>
                    <th scope="col">Title</th>
                    <th scope="col">Author</th>
                    <th scope="col">Publication Year</th>
                    <th scope="col">Genre</th>
                </tr>
            </thead>
            <tbody>
                @foreach($books as $book)
                <tr>
                    <th scope="row">{{ $book->id }}</th>
                    <td>{{ $book->title }}</td>
                    <td>{{ $book->author }}</td>
                    <td>{{ $book->publication_year }}</td>
                    <td>{{ $book->genre }}</td>
                </tr>
                @endforeach
            </tbody>
        </table>
    </div>
    <script src="{{ asset('js/app.js') }}" type="text/js"></script>
</body>
</html>

 

Step 6: Setup Database with Books Table

In this section, we will follow the steps to create a dummy Books table data to create the dynamic PDF file.

Create Books Model

We will populate dummy data of Books, for that create a model by executing the below command:

php artisan make:model Book -m

It will generate a new file app/Models/Book.php, update it with following:

<?php

namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Book extends Model
{
    use HasFactory;
}

Create a Factory for Generating Fake Data

We will define a factory to generating fake data for our model. Execute following command to create a Factory:

php artisan make:factory BookFactory

Update the newly created factory at this location database/factories/BookFactory.php with following:

<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

class BookFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'title' => $this->faker->sentence(3),
            'author' => $this->faker->name,
            'published_at' => $this->faker->date($format = 'Y-m-d', $max = 'now'),
            // Add more book attributes as needed
        ];
    }
}

Create and Define the Schema in the Migration

Now create a new migration file by executing below command:

php artisan make:migration create_books_table

It will create a new migration file at this location database/migrations/current_timestamp_create_books_table.php, which you need to update as below:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateBooksTable extends Migration
{
    public function up()
    {
        Schema::create('books', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->string('author');
            $table->date('publication_date');
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('books');
    }
}

The up() function will create the rows with a defined structure. If you want to revert the action, the down() the function will drop the books table.

 

Migrate the Database

Run the migration command to create the books table:

php artisan migrate

Seed the Database with Fake Data

Create a new seeder class named BooksTableSeeder.php in the database/seeders directory by executing the below command:

php artisan make:seeder BooksTableSeeder

 

In the BooksTableSeeder.php file, we will seed the books table with fake data. Update the file as below:

<?php

namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Faker\Factory as Faker;

class BooksTableSeeder extends Seeder
{
    public function run()
    {
        $faker = Faker::create();

        foreach (range(1, 10) as $index) {
            DB::table('books')->insert([
                'title' => $faker->sentence,
                'author' => $faker->name,
                'publication_date' => $faker->date($format = 'Y-m-d', $max = 'now'),
            ]);
        }
    }
}

 

Run the Seeder

Finally, run the seeder command to populate the books table with fake data:

 php artisan db:seed --class=BooksTableSeeder

 

Start the Laravel Application

Finally, start the server, run the following command from your project directory:

php artisan serve

Now you will see your application running at http://127.0.0.1:8000/

Generate Dynamic PDF in Laravel - FreakyJolly.com

Configuring Page Options (Orientation, Margins, Paper Size)

We already discussed how we can configure the DomPDF properties, but you can also configure page options such as orientation, margins, and paper size, you can pass an array of options when loading the view. Update the generatePDF() function in the controller as below:

    public function generatePDF()
    {
        $books = Book::all();
        $pdf = \Barryvdh\DomPDF\Facade\Pdf::loadView('books', compact('books'));

        $pdf->setPaper('A4', 'landscape'); // Set paper size and orientation
        $pdf->setOption('margin-top', 10); // Set top margin
        $pdf->setOption('margin-right', 20); // Set right margin
        $pdf->setOption('margin-bottom', 10); // Set bottom margin
        $pdf->setOption('margin-left', 20); // Set left margin

        // Other available options can be set similarly

        // Download the PDF with a specific file name
        return $pdf->download('book_list.pdf');

    }

 

Previewing the PDF Instead of Downloading

To preview the PDF in the browser instead of downloading it, we can use the stream instead of download to open the PDF file in the new tab instead of downloading. Here’s an example:

    public function generatePDF()
    {
        $books = Book::all();
        $pdf = \Barryvdh\DomPDF\Facade\Pdf::loadView('books', compact('books'));

        // Download the PDF with a specific file name
        // return $pdf->download('book_list.pdf');


        // Preview the PDF with a specific file name
        return $pdf->stream('book_list.pdf');
    }

 

Conclusion

We have finally integrated the dynamic PDF generation functionality in the Laravel 9 application. We also discussed how to download or preview the PDF file in a browser. In the above guide, we discussed how to create Models, Factories, Controllers and Seeders to populate databases with dummy data to test our PDF generation functionality.

Laravel DomPDF package provides a wide variety of configurational features to modify page layout, margin, page size etc as we discussed. You can easily extent the discussed implementations to create complex views.

Hope this will be helpful.

Leave a Comment

Your email address will not be published. Required fields are marked *