🚀 Generate Dynamic PDFs in Laravel with DomPDF

blamsa0mine

A0mineTV

Posted on November 30, 2024

🚀 Generate Dynamic PDFs in Laravel with DomPDF

Generate Dynamic PDFs in Laravel with DomPDF

Have you ever needed to create PDF files in a Laravel application? Perhaps for invoices, reports, or even simple lists? This guide will teach you how to use DomPDF, a popular library for PDF generation, to create dynamic and professional-looking PDFs in your Laravel app. For this example, we’ll generate a PDF of a student list.


Why DomPDF?

DomPDF is a PHP library that converts HTML and CSS into PDF documents. It’s easy to integrate with Laravel, and you can use your existing Blade templates to define the structure and styling of your PDFs. No need to learn a new syntax!


What You’ll Build

We’ll build a Laravel app that:

  • Displays a list of students.

  • Provides a “Download PDF” button to export the student list as a PDF.


Prerequisites

Before starting, make sure you have the following installed:

  • PHP 8.x or higher

  • Composer

  • Laravel 10 or higher

  • A configured database (e.g., MySQL)


Step 1: Install DomPDF

First, install the DomPDF package via Composer:

composer require barryvdh/laravel-dompdf
Enter fullscreen mode Exit fullscreen mode

DomPDF will automatically be registered in Laravel. If you need to, you can manually add it to the providers and aliases sections in config/app.php:

'providers' => [
    Barryvdh\DomPDF\ServiceProvider::class,
],
'aliases' => [
    "PDF" => \Barryvdh\DomPDF\Facade\Pdf::class
]
Enter fullscreen mode Exit fullscreen mode

Step 2: Create the Student Model and Migration

Let’s create a Student model with a migration file:

php artisan make:model Student -m
Enter fullscreen mode Exit fullscreen mode

Open the migration file in database/migrations and define the table schema:

public function up(): void
    {
        Schema::create('students', function (Blueprint $table) {
            $table->id();
            $table->string('firstname');
            $table->string('lastname');
            $table->string('email')->unique();
            $table->string('name_util');
            $table->string('telephone');
            $table->date('birthday');
            $table->string('gender');
            $table->timestamps();
        });
    }

Enter fullscreen mode Exit fullscreen mode

Run the migration:

php artisan migrate
Enter fullscreen mode Exit fullscreen mode

Step 3: Seed the Database with Students

To test our app, we need sample student data. Create a factory:

php artisan make:factory StudentFactory --model=Student
Enter fullscreen mode Exit fullscreen mode

Define the factory data in database/factories/StudentFactory.php:

public function definition()
{
    return [
        'firstname' => $this->faker->firstName(),
        'lastname' => $this->faker->lastName(),
        'email' => $this->faker->unique()->safeEmail(),
        'name_util' => $this->faker->userName(),
        'telephone' => $this->faker->phoneNumber(),
        'birthday' => $this->faker->date(),
        'gender' => $this->faker->randomElement(['Male', 'Female']),
    ];
}
Enter fullscreen mode Exit fullscreen mode

Update the DatabaseSeeder.php file:

Student::factory(100)->create();
Enter fullscreen mode Exit fullscreen mode

Seed the database:

php artisan db:seed
Enter fullscreen mode Exit fullscreen mode

Step 4: Create the Controller

Create a controller to handle displaying the student list and generating the PDF:

php artisan make:controller StudentPDFController
Enter fullscreen mode Exit fullscreen mode

In StudentPDFController.php, add the following methods:

<?php

declare(strict_types=1);

namespace App\Http\Controllers;

use App\Models\Student;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\App;

final class StudentPDFController extends Controller
{
    public function index(): Factory|View|Application
    {
        $studentData = $this->getStudentData();
        return view('list_students_pdf', compact('studentData'));
    }

    public function pdf()
    {
        $pdf = App::make('dompdf.wrapper');
        $pdf->loadHTML($this->convertStudentDataToHtml());
        $pdf->getDomPDF()->set_option('enable_php', true);
        $pdf->setPaper('a4', 'landscape');
        return $pdf->stream();
    }

    protected function convertStudentDataToHtml(): string
    {
        $studentData = $this->getStudentData();

        $output = '
            <h3 align="center">List of students</h3>
            <table width="100%" style="border-collapse: collapse; border: 0px;">
                <tr>
                    <th style="border: 1px solid; padding: 6px; width: 10%">ID</th>
                    <th style="border: 1px solid; padding: 6px; width: 20%">Firstname</th>
                    <th style="border: 1px solid; padding: 6px; width: 20%">Lastname</th>
                    <th style="border: 1px solid; padding: 6px; width: 20%">User</th>
                    <th style="border: 1px solid; padding: 6px; width: 10%">Téléphone</th>
                    <th style="border: 1px solid; padding: 6px; width: 10%">Birthday</th>
                    <th style="border: 1px solid; padding: 6px; width: 10%">Gender</th>
                </tr>
        ';
        foreach ($studentData as $student) {
            $output .= '
                 <tr>
                    <td style="border: 1px solid; padding: 6px">'. $student->id .'</td>
                    <td style="border: 1px solid; padding: 6px">'. $student->firstname .'</td>
                    <td style="border: 1px solid; padding: 6px">'. $student->lastname .'</td>
                    <td style="border: 1px solid; padding: 6px">'. $student->name_util .'</td>
                    <td style="border: 1px solid; padding: 6px">'. $student->telephone .'</td>
                    <td style="border: 1px solid; padding: 6px">'. $student->birthday .'</td>
                    <td style="border: 1px solid; padding: 6px">'. $student->gender .'</td>
                </tr>
            ';
        }
        $output .= "</table>";
        $output .= '<script type="text/PHP">
            if (isset($pdf)) {
                $text = "Page : {PAGE_NUM}/{PAGE_COUNT}";
                $size = 10;
                $font = $fontMetrics->getFont("Verdana");
                $width = $fontMetrics->get_text_width($text, $font, $size) / 2;
                $x = ($pdf->get_width() - $width) / 2;
                $y = $pdf->get_height() - 35;
                $pdf->page_text($x, $y, $text, $font, $size);
            }
        </script>';

        return $output;
    }

    protected function getStudentData()
    {
        return Student::get();
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 5: Create the Blade View

Create a Blade file at resources/views/list_students_pdf.blade.php:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"
          integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
    <style type="text/css">
        .box {
            width: 600px;
            margin: 0 auto;
        }
    </style>
</head>
<body>
<br/>
<div class="container">
    <h3 align="center">Generate a PDF file with laravel DomPDF</h3>
    <br/>
    <div class="row">
        <div class="col-md-7" align="right">
            <h4>Student Data</h4>
        </div>
        <div class="col-md-5" align="right">
            <a href="{{ url('list_students_pdf/pdf') }}">Download PDF</a>
        </div>
    </div>
    <br/>
    <div class="table-responsive">
        <table class="table table-striped table-bordered">
            <thead>
            <tr>
                <th>ID</th>
                <th>Firstname</th>
                <th>Lastname</th>
                <th>Email</th>
                <th>User</th>
                <th>Telephone</th>
                <th>Birthday</th>
                <th>Gender</th>
            </tr>
            </thead>
            <tbody>
                @foreach($studentData as $student)
                    <tr>
                        <td>{{ $student->id }}</td>
                        <td>{{ $student->firstname }}</td>
                        <td>{{ $student->lastname }}</td>
                        <td>{{ $student->email }}</td>
                        <td>{{ $student->name_util }}</td>
                        <td>{{ $student->telephone }}</td>
                        <td>{{ $student->birthday }}</td>
                        <td>{{ $student->gender }}</td>
                    </tr>
                @endforeach
            </tbody>
        </table>
    </div>
</div>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

 Step 6: Add Routes

In routes/web.php:

Route::get('/list_students_pdf', [StudentPDFController::class, 'index']);
Route::get('/list_students_pdf/pdf', [StudentPDFController::class, 'pdf']);
Enter fullscreen mode Exit fullscreen mode

Step 7: Test Your Application

  • Visit /list_students_pdf to view the student list.

  • Click "Download PDF" to generate and display the PDF.


đź“‚ Code source

Find the complete code on GitHub : laravel_pdf


 Conclusion

Congratulations! 🎉 You’ve built a Laravel app that dynamically generates a PDF from a database. This project demonstrates how easy it is to use Laravel and DomPDF together for document generation. Start using this approach for your invoices, reports, or any document-based projects !

đź’– đź’Ş đź™… đźš©
blamsa0mine
A0mineTV

Posted on November 30, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related