Saturday, April 22, 2017

Generate PDF in CakePHP 3.x with CakePDF And DomPDF

At first you need to install CakePDF to your project. Add "friendsofcake/cakepdf": "3.2.*" to "composer.json" file under "require" section as follows:

"require": {

    "friendsofcake/cakepdf": "3.2.*"

}

Now open command panel and navigate to project directory and execute:

composer update friendsofcake/cakepdf --lock


Or you can direct execute the command "composer require friendsofcake/cakepdf" to install CakePDF. This command will install a suitable latest version to your project.


Above command will install CakePDF to your project.


Next step is to install DomPDF.


Execute following command to install DomPDF
"composer require dompdf/dompdf".


Installation complete, now add the following line to "config/bootstrap.php" file:


Plugin::load('CakePdf', ['bootstrap' => true]);


Configure::write('CakePdf', [

    'engine' => [
        'className' => 'CakePdf.Dompdf',
        'options' => [
            'print-media-type' => false,
            'outline' => true,
            'dpi' => 96
        ]
    ],
    'pageSize' => 'Letter',
]);
define('DOMPDF_ENABLE_AUTOLOAD', false);
define('DOMPDF_ENABLE_HTML5PARSER', true);
define('DOMPDF_ENABLE_REMOTE', true);


Configuration options:
  • engine: Engine to be used (required), or an array of engine config options
    • className: Engine class to use
    • options: Engine specific options. Currently only for WkHtmlToPdf, where the options are passed as CLI arguments, and for DomPdf, where the options are passed to the DomPdf class constructor.
  • crypto: Crypto engine to be used, or an array of crypto config options
    • className: Crypto class to use
    • binary: Binary file to use
  • pageSize: Change the default size, defaults to A4
  • orientation: Change the default orientation, defaults to portrait
  • margin: Array or margins with the keys: bottom, left, right, top and their values
  • title: Title of the document
  • delay: A delay in milliseconds to wait before rendering the pdf
  • windowStatus: The required window status before rendering the PDF
  • encoding: Change the encoding, defaults to UTF-8
  • download: Set to true to force a download, only when using PdfView
  • filename: Filename for the document when using forced download

Now we can do 3 things with our CakePDF
1. Download PDF
2. Stream PDF to browser
3. Save PDF to our server

Lets go for download & stream PDF:

Add the following code block in "config/router.php" file:


Router::scope('/pdf_download/:id', function (RouteBuilder $routes) {

    $routes->addExtensions(['pdf']);
    $routes->connect('/', ['controller' => 'Pages', 'action' => 'cakePdfDownload']);

});

Now in your "PagesController.php" add below code snippet:


public function cakePdfDownload($name = null)

{
    Configure::write('CakePdf.download', true);
    Configure::write('CakePdf.filename', "MyCustomName.pdf");

}

Now need to create a layout file for pdf. Create "default.ctp" under "Template/Layout/Pdf" directory with following contents:


<?php

use Cake\Core\Configure;
$cakeDescription = 'CakePHP: the rapid development PHP framework';
?>
<!DOCTYPE html>
<html>
<head>
    <?= $this->Html->charset() ?>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>
        <?= $cakeDescription ?>:
        <?= $this->fetch('title') ?>
    </title>

    <?= $this->Html->meta('icon') ?>

    <?= $this->Html->css('base.css', ['fullBase' => true]) ?>
    <?= $this->Html->css('cake.css', ['fullBase' => true]) ?>
    <?= $this->Html->css('home.css', ['fullBase' => true]) ?>
    <link href="https://fonts.googleapis.com/css?family=Raleway:500i|Roboto:300,400,700|Roboto+Mono" rel="stylesheet">
</head>
<body class="home">

<header class="row">

    <div class="header-image"><?= $this->Html->image('cake.logo.svg') ?></div>
    <div class="header-title">
        <h1>Welcome to CakePHP <?= Configure::version() ?> Red Velvet. Build fast. Grow solid.</h1>
    </div>
</header>
<div class="row">
    <div class="columns large-12">
        <?= $this->fetch('content') ?>
    </div>
</div>
</body>

</html>

'fullBase' => true for create permanent link to resources.


Now create a file named "cake_pdf_download.ctp" under "Template/Pages/Pdf" directory with any content.


You are done, you browse "http://localhost/cake/pdf_download/invoice.pdf" then a pdf will be downloaded because we set "Configure::write('CakePdf.download', true);" if we set false here as "Configure::write('CakePdf.download', false);" then PDF will not be downloaded but will be rendered in browser itself.






Now go for save PDF to our server:


public function cakePdf()

{
    $CakePdf = new \CakePdf\Pdf\CakePdf();
    $CakePdf->template('cake_pdf', 'default');
    $CakePdf->viewVars($this->viewVars);
    $pdf = $CakePdf->write(APP . 'Files' . DS . 'Output.pdf');
    echo $pdf;die();

}

And finally you are done CakePDF with DomPDF.

4 comments:

  1. Error
    Not Found
    Error: The requested address '/pdf_download/invoice.pdf' was not found on this server.

    ReplyDelete
  2. Error
    Not Found
    Error: The requested address '/pdf_download/invoice.pdf' was not found on this server.

    ReplyDelete
  3. Hi,

    i am not able to load image, i have self signed certificate so perhaps, i have tried to set setHttpContext but no luck, project is on linux debian 10, image is loading locally find, because it's http image so, when i load http image from other server it's work but not with https

    need help

    ReplyDelete