Create PDF in Laravel Tutorial
Tags: laravel, php, programming, webdev
Published: 2022-01-19 16:05:35

---
title: Create PDF in Laravel Tutorial
published: true
date: 2022-01-19 08:48:05 UTC
tags: Laravel,PHP,programming,webdev
canonical_url: https://blog.shahednasser.com/create-pdf-in-laravel-tutorial/
cover_image: https://blog.shahednasser.com/static/73eecbeb674f24af57f306eecd68e86e/Create-PDF-with-Laravel-Tutorial-7.png
---

_This was originally published on [my personal blog](https://blog.shahednasser.com/create-pdf-in-laravel-tutorial/)._

[Laravel](https://laravel.com) is one of the most popular web development frameworks. It allows you to create fast, modern, and scalable websites for almost every use case.

In this tutorial, you'll learn how to create PDF files using Laravel and [mPDF](https://mpdf.github.io). You'll create a website that shows the user a rich text editor where they can add whatever content they want, then transform that content into a PDF file.

You can find the full code for the tutorial at [this GitHub repository](https://github.com/shahednasser/laravel-pdf-tutorial).

## Prerequisites

To follow along with this tutorial, you need to have [PHP](https://www.php.net) installed. As this tutorial uses Laravel 8 and mPDF v8 (the latest versions at the time of writing), you should have a 7.3 or 7.4 PHP version, as mPDF only supports up to version 7.4.

You also need to have [Composer](https://getcomposer.org/download/) installed.

## Project Setup

In this section, you'll set up a Laravel project. Open your terminal and run the following command:

```bash
composer create-project laravel/laravel laravel-pdf-tutorial
```

This will create the directory `laravel-pdf-tutorial` with the Laravel installation inside.

Once it's done, change to that directory and install mPDF to be used later:

```bash
composer require mpdf/mpdf
```

## Create Page

As mentioned, you'll create a web page that will show the user a text editor that they can use to enter any content they want. It'll also show some configurations for creating the PDF file.

Create the file `resources/views/home.blade.php` with the following content:

```html
<!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">
  <title>PDF Maker</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" 
    integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
  <script src="https://cdn.tiny.cloud/1/no-api-key/tinymce/5/tinymce.min.js" referrerpolicy="origin"></script>
  <script>
    tinymce.init({
      selector: '.editor',
      toolbar: 
        'styleselect | alignleft aligncenter alignright | bold italic underline strikethrough | image | bullist numlist | table',
      plugins: 'image lists table',
      automatic_uploads: true,
      file_picker_types: 'image',
      file_picker_callback: function (cb, value, meta) {
        var input = document.createElement('input');
        input.setAttribute('type', 'file');
        input.setAttribute('accept', 'image/*');

        input.onchange = function () {
          var file = this.files[0];

          var reader = new FileReader();
          reader.onload = function () {
            var id = 'blobid' + (new Date()).getTime();
            var blobCache = tinymce.activeEditor.editorUpload.blobCache;
            var base64 = reader.result.split(',')[1];
            var blobInfo = blobCache.create(id, file, base64);
            blobCache.add(blobInfo);
            cb(blobInfo.blobUri(), { title: file.name });
          };
          reader.readAsDataURL(file);
        };

        input.click();
      },
    });
  </script>
</head>
<body>
  <div class="container my-4 mx-auto">
    <form action="#" method="POST">
      @csrf
      <h1>PDF Maker</h1>
      <h2>Configurations</h2>
      <div class="mb-3">
        <label for="name" class="form-label">PDF Name</label>
        <input type="text" class="form-control" id="name" name="name" />
      </div>
      <div class="mb-3">
        <label for="header" class="form-label">Header</label>
        <textarea name="header" id="header" class="editor"></textarea>
      </div>
      <div class="mb-3">
        <label for="footer" class="form-label">Footer</label>
        <div id="footerHelp" class="form-text">You can use {PAGENO} to add page numbering to all pages</div>
        <textarea name="footer" id="footer" class="editor"></textarea>
      </div>
      <div class="form-check mb-3">
        <input class="form-check-input" type="checkbox" id="show_toc" name="show_toc">
        <label class="form-check-label" for="show_toc">
          Show Table of Content?
        </label>
      </div>
      <h2>Content</h2>
      <textarea name="content" id="content" class="editor"></textarea>
      <div class="text-center">
        <button type="button" class="btn btn-primary">Create</button>
      </div>
    </form>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
</body>
</html>
```

In this code, we show a form with configurations and a text editor for the content. We use [Bootstrap](https://getbootstrap.com) for easy styling, and [TinyMCE](https://www.tiny.cloud/docs/quick-start/) to easily insert an editor in our form. With TinyMCE, we also add an image picker based on [this example](https://www.tiny.cloud/docs/demo/file-picker/) from their documentation.

For the configurations, we show a field to enter the name of the PDF, a text editor to style the header, a text editor to style the footer, and a checkbox to enable or disable the table of content.

Next, in `routes/web.php` change the route for the home page to the following:

```php
Route::get('/', function () {
    return view('home');
});
```

Now, run the server:

```bash
php artisan serve
```

If you open the website now at `localhost:8000` (by default), you'll see the form we just created.

![Create PDF in Laravel Tutorial](https://backend.shahednasser.com/content/images/2022/01/Screen-Shot-2022-01-18-at-6.33.29-PM.png)
_PDF Maker Home Page_

If you see a notice on the editors regarding an API key, this is because we're using the CDN without an API key. You can obtain an API key by signing up to [Tiny Cloud](https://www.tiny.cloud/auth/signup/), or by [downloading and self-hosting](https://www.tiny.cloud/get-tiny/self-hosted/) the TinyMCE library.

Notice that for the footer, we add a note that to add a page number to all pages we can use the placeholder `{PAGENO}`. This can be added to the header or footer.

## Create PDF

In this section, you'll create the controller that will handle the form submission and create the PDF.

In your terminal, run the following command:

```bash
php artisan make:controller PdfController
```

Then, open the controller at `app/Http/Controllers/PdfController.php` and place the following method inside the class:

```php
public function createPdf (Request $request) {
        //validate request
        Validator::validate($request->all(), [
            'name' => 'required|string|min:1',
            'content' => 'required|string|min:1'
        ]);

        //create PDF
        $mpdf = new Mpdf();

        $header = trim($request->get('header', ''));
        $footer = trim($request->get('footer', ''));

        if (strlen($header)) {
            $mpdf->SetHTMLHeader($header);
        }

        if (strlen($footer)) {
            $mpdf->SetHTMLFooter($footer);
        }

        if ($request->get('show_toc')) {
            $mpdf->h2toc = array(
                'H1' => 0,
                'H2' => 1,
                'H3' => 2,
                'H4' => 3,
                'H5' => 4,
                'H6' => 5
            );
            $mpdf->TOCpagebreak();
        }

        //write content
        $mpdf->WriteHTML($request->get('content'));

        //return the PDF for download
        return $mpdf->Output($request->get('name') . '.pdf', Destination::DOWNLOAD);
    }
```

Make sure to also add the necessary imports at the beginning of the file:

```php
use Illuminate\Support\Facades\Validator;
use Mpdf\Mpdf;
use Mpdf\Output\Destination;
```

First, you validate the request using Laravel's Validate Facade. You can learn more about Laravel's Validation in [this tutorial](https://blog.shahednasser.com/beginners-guide-to-validation-in-laravel).

After validating the request parameters, you create a new instance of `Mpdf`. You can pass [a lot of configurations to mPDF's constructor](https://mpdf.github.io/configuration/configuration-v7-x.html) which allows you to set things like the font used or the text direction.

Next, you retrieve the values for Header and Footer entered by the user. If there are any entered, you set the Header with `SetHTMLHeader` and Footer with `SetHTMLFooter`. This will set the header and footer on all pages.

Then, you check if `show_toc` was checked. If it was, you add a Table of Content at the beginning of the PDF using `TOCpagebreak`. You also use the mPDF instance's `h2toc` parameter to define the hierarchy that should be used in the table of content. This makes it easier for `Mpdf` to generate the table of content from the PDF's content.

Next, you set the content of the PDF using `WriteHTML`. You will write the `content` entered by the user as is. Since TinyMCE sends the content to the server as HTML, the content should look exactly the same in the editor as it is in the PDF.

Finally, you return the PDF for download using the `Output` method. This method receives as a first parameter the file name, and as a second parameter the return type. Its values can be `I` for inline (default behavior), `D` for download which will force download in the browser, `F` for file which should be used when storing the created file, and `S` for String Return which should be used when the PDF should be returned as a string.

In this case, you use `D` which will create the PDF and trigger the download automatically.

Now that the controller's method is finished, add the new route in `routes/web.php`:

```php
Route::post('/create', [App\Http\Controllers\PdfController::class, 'createPdf']);
```

And change the `action` attribute of the form in `resources/views/home.blade.php`:

```html
<form action="/create" method="POST">
```

That's all! Now, open the home page again and enter all the content you want. You can enter images, tables, lists, and more. Once you're done, click on Create, and the PDF will be generated and downloaded. Notice how the content is exactly similar to how it looks in the editor.

## Bonus: Adding Stylesheets

mPDF allows you to add styling to your PDF document. You can pass it as a stylesheet as follows:

```php
$stylesheet = "h1 { color: red; }";
$mpdf->WriteHTML($stylesheet,\Mpdf\HTMLParserMode::HEADER_CSS);
```

## Conclusion

There are a lot of use cases where you would need to create a PDF file. In Larave, you can easily do that using mPDF. There are so many functionalities and things you can do with mPDF so be sure to check out [their documentation](https://mpdf.github.io/getting-started/creating-your-first-file.html).