# CakePHP 4 Print PDF Using CakePDF

> This tutorial will show how to use the CakePDF plugin to generate a PDF file. This tutorial will use DOMPDF as an example of the generator engine. Basically, generating PDF is useful for those who are working with a system that prints or produce correspondence or document related task.

- URL: https://codethepixel.com/cakephp-4-print-pdf-using-cakepdf
- Author: Asyraf Wahi Anuar (https://codethepixel.com/author/asyraf-wahi-anuar)
- Published: 2020-05-17
- Updated: 2022-02-11
- Category: CakePHP
- Tested with: CakePHP 4.x
- Tags: CakePHP, CakePDF, PDF, Print
- Reading time: 6 min

This tutorial will show how to use the [CakePDF plugin](https://github.com/FriendsOfCake/CakePdf/tree/cake-4.x) to generate a PDF file. This tutorial will use DOMPDF as an example of the generator engine. Basically, generating PDF is useful for those who are working with a system that prints or produce correspondence or document related task.

## Download and Load CakePDF Plugin

Download CakePDF plugin via composer:

```bash
$ composer require friendsofcake/cakepdf
```

Load the plugin using the console:

```bash
$ bin/cake plugin load CakePdf
```

or manually add the following code to ...\\src\\Application.php

`src/Application.php`

```php
$this->addPlugin('CakePdf');
```

## PDF Engine

The plugin does not include the PDF generator engine. You need to download the engine. Depending on what engine you want to use, you need to download them to your project. DomPdf, Mpdf and Tcpdf can be installed via composer using one of the following commands:

```bash
$ composer require dompdf/dompdf
$ composer require tecnickcom/tcpdf
$ composer require mpdf/mpdf
```

You also can use [WkHtmlToPdf ](https://wkhtmltopdf.org/downloads.html)which can be downloaded from the webpage.

## Engine Configuration

At the end of the file, load the following codes. Replace the "Dompdf" engine with the one you intend to use yourself.

`config/bootstrap.php`

```php
Configure::write('CakePdf', [
    'engine' => [
        'className' => 'CakePdf.DomPdf',
        'options' => [
            'isRemoteEnabled' => true
        ]
    ],
    'margin' => [
        'bottom' => 10,
        'left' => 10,
        'right' => 10,
        'top' => 10
    ],
    'orientation' => 'portrait',
    'download' => true
]);
```

If use WkHtmlToPdf, specify the binary full path:

```php
'binary' => 'C:\wkhtmltopdf\bin\wkhtmltopdf.exe'
```

## Controller

Depending on which controller you need to generate the PDF, create a new public function pdf:

```php
public function pdf($id = null)
{
    $this->viewBuilder()->enableAutoLayout(false); 
    $report = $this->Reports->get($id);
    $this->viewBuilder()->setClassName('CakePdf.Pdf');
    $this->viewBuilder()->setOption(
        'pdfConfig',
        [
            'orientation' => 'portrait',
            'download' => true, // This can be omitted if "filename" is specified.
            'filename' => 'Report_' . $id . '.pdf' //// This can be omitted if you want file name based on URL.
        ]
    );
    $this->set('report', $report);
}
```

If you want to use the title as the filename, use the following codes:

```php
'filename' => \Cake\Utility\Text::slug($report->title) . '-' . __('Report') . '.pdf'
```

## Template

Create the view templates in a 'pdf' subdir, for instance, templates/Reports/pdf/pdf.php and add the following codes into pdf.php file

`Reports/pdf/pdf.php`

```php
<!DOCTYPE html>
<html>
<head>
<title>PDF</title>
<style>
@page {
    margin: 0px 0px 0px 0px !important;
    padding: 0px 0px 0px 0px !important;
}
</style>
</head>
<body>
<?= h($report->title) ?>
</body>
</html>
```

## Download Link

In your view.php file, add the following code to call the pdf page:

```php
<?= $this->Html->link(__('Download PDF'), ['action' => 'pdf', $report->id ]) ?>
```

## Insert Image in PDF

It required fullbase set to true as follows:

```php
<?= $this->Html->image('myImage.png', ['fullBase' => true]); ?>
```

## Insert CSS in PDF

It required fullbase set to true as follows:

```php
<?= $this->Html->css('pdf.css', ['fullBase' => true]) ?>
```

Now you should be able to generate the pdf file and download it. For CSS, just create and link it to the pdf template or just add it to the style.

## Save PDF to Server

To generate and save the PDF into a webserver, use the following code:

```php
public function pdf($id = null)
{
    $this->viewBuilder()->enableAutoLayout(false); 
    $report = $this->Reports->get($id);
    $this->viewBuilder()->setClassName('CakePdf.Pdf');
    $this->viewBuilder()->setOption(
        'pdfConfig',
        [
            'orientation' => 'portrait',
            'download' => true, // This can be omitted if "filename" is specified.
            'filename' => 'Report_' . $id . '.pdf' // This can be omitted if you want file name based on URL.
        ]
    );
	//Write and Save PDF to folder
	$CakePdf = new \CakePdf\Pdf\CakePdf();
	$CakePdf->template('report', 'default');
	$CakePdf->viewVars([
		'title' => $report->title, //variables eg
		'body' => $report->body,
	]);
	// Get the PDF string returned
	$pdf = $CakePdf->output();
	// Or write it to file directly
	$pdf = $CakePdf->write('files' . DS . 'pdf' . DS . $id . '.pdf'); //stored in ...webroot/files/pdf/1.pdf
	
    $this->set('report', $report, 'title', 'body');
}
```

Create default template at ...\\templates\\layout\\pdf\\default.php and use the viewVars eg:

`templates/layout/pdf/default.php`

```php
<!DOCTYPE html>
<html>
<head>
<title>PDF</title>
<?php
use Cake\Routing\Router;
?>
<style>
@page {
	margin-top: 50px !important;
	margin-bottom: 50px !important;
	margin-right: 50px !important;
	margin-left: 50px !important;
    padding: 0px 0px 0px 0px !important;
}
body{
	font-family: 'Roboto', sans-serif;
}
</style>
</head>
<body>
Hello<br/>
<?= $title; ?>
<br/>
<?= $body; ?>
</body>
</html>
```

## Email Saved PDF as Email Attachment

To email the saved PDF as an attachment, use the following code. [Read more about CakePHP 4 Email.](/cakephp-4-sending-email)

```php
public function pdf($id = null)
{
    $this->viewBuilder()->enableAutoLayout(false); 
    $report = $this->Reports->get($id);
    $this->viewBuilder()->setClassName('CakePdf.Pdf');
    $this->viewBuilder()->setOption(
        'pdfConfig',
        [
            'orientation' => 'portrait',
            'download' => true, // This can be omitted if "filename" is specified.
            'filename' => 'Report_' . $id . '.pdf' //// This can be omitted if you want file name based on URL.
        ]
    );
	//Write and Save PDF to folder
	$CakePdf = new \CakePdf\Pdf\CakePdf();
	$CakePdf->template('report', 'default');
	$CakePdf->viewVars([
		'title' => $report->title, //variables eg
		'body' => $report->body,
	]);
	// Get the PDF string returned
	$pdf = $CakePdf->output();
	// Or write it to file directly
	$pdf = $CakePdf->write('files' . DS . 'pdf' . DS . $id . '.pdf');
	
	//Email with attachment
	$mailer = new Mailer('default');
	$mailer
		->setTransport('smtp');
		->setAttachments(['files' . DS . 'pdf' . DS . $id . '.pdf']); //get saved PDF file
		->setFrom(['noreply@codethep!xel.com' => 'Code The Pixel'])
		->setTo('receiver@example.com') //receiver email
		->setEmailFormat('html')
		->setSubject('Report') //email subject
		->deliver('Report in PDF'); //content

		return $this->redirect($this->referer());
	
    $this->set('report', $report, 'title', 'body');
}
```

That all. Happy coding :)
