danfekete / phpwkhtmltopdf

A slim PHP wrapper around wkhtmltopdf with an easy to use and clean OOP interface

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

PHP WkHtmlToPdf

PHP WkHtmlToPdf provides a simple and clean interface to ease PDF creation with wkhtmltopdf.

The wkhtmltopdf command must be installed and working on your system. See the section below for details.

Quickstart

<?php
require_once('WkHtmlToPdf.php');

$pdf = new WkHtmlToPdf;

// Add a HTML file, a HTML string or a page from a URL
$pdf->addPage('/home/joe/page.html');
$pdf->addPage('<html>....</html>');
$pdf->addPage('http://google.com');

// Add a cover (same sources as above are possible)
$pdf->addCover('mycover.html');

// Add a Table of contents
$pdf->addToc();

// Save the PDF
$pdf->saveAs('/tmp/new.pdf');

// ... or send to client for inline display
$pdf->send();

// ... or send to client as file download
$pdf->send('test.pdf');

Setting options

The wkhtmltopdf shell command accepts different types of options:

  • global options (e.g. to set the document's DPI)
  • page options (e.g. to supply a custom CSS file for a page)
  • toc options (e.g. to set a TOC header)

Please see wkhtmltopdf -H for a full explanation. All options are passed as array, for example:

// Global PDF options
$options = array(
    'no-outline',           // option without argument
    'encoding' => 'UTF-8',  // option with argument
);
$pdf = new WkHtmlToPdf($options);

Page options can be supplied on each call to addPage(). But you can also set default options that will be applied to all pages:

$pdf = new WkHtmlToPdf($globalOptions); // Set global PDF options
$pdf->setOptions($globalOptions);       // Set global PDF options (alternative)
$pdf->setPageOptions($pageOptions);     // Set default page options
$pdf->addPage($page, $pageOptions);     // Add page with options (overrides default page options)
$pdf->addCover($page, $pageOptions);    // Add cover with options (overrides default page options)

Toc options can be passed to addToc():

$pdf->addToc($tocOptions);              // Add TOC with options

Since 1.2.2 you can also pass repeatable options like cookie or run-script:

$pdf->addPage($page, array(
    // Repeatable options with <name> <value> arguments
    'cookie' => array(
        'PHPSESSID' => $session_id,
        'marketing_flag' => 1,
    ),
    // Repeatable options with single argument
    'run-script' => array(
        'local1.js',
        'local2.js',
    ),
));

And since 1.2.4 you can also supply a custom HTML string as header-html and footer-html. The string must contain at least one HTML tag, though.

Special global options

There are some special options to configure PHP wrapper. They can be passed to the constructor or be set via setOptions():

  • binPath: Full path to the wkhtmltopdf shell command. Required on Windows systems and optionally autodetected if not set on other OS.
  • binName: Base name of the binary to use for autodetection. Default is wkhtmltopdf.
  • tmp: Path to tmp directory. Defaults to the PHP temp dir.
  • ignoreWarnings: Whether to ignore any errors if a PDF file was still created. Default is false.
  • enableEscaping: Whether arguments to wkhtmltopdf should be escaped. Default is true.
  • version9: Whether to use command line syntax for wkhtmltopdf < 0.10.
  • procEnv: Optional array with environment variables for shell command.
  • enableXvfb: Whether to use the built in Xvfb support (see below). Default is false.
  • xvfbRunBin: Path to xvfb-run binary (see below). Default is to autodetect the binary.
  • xvfbRunOptions: Options for the xvfb-run command (see below). Default is --server-args="-screen 0, 1024x768x24".

Error handling

send(), saveAs() and save() will return false on error. In this case the detailed error message from wkhtmltopdf is available from getError():

<?php
if (!$pdf->send()) {
    throw new Exception('Could not create PDF: '.$pdf->getError());
}

Note for Windows users

If you use double quotes (") or percent signs (%) as option values, they may get converted to spaces. You can set enableEscaping to false in this case. But then you have to take care of proper escaping yourself. In some cases it may be neccessary to surround your argument values with extra double quotes.

I also found that some options don't work on Windows (tested with wkhtmltopdf 0.11 rc2), like the user-style-sheet option described below.

Setup for different wkhtmltopdf versions

As mentioned before the PHP class is just a convenient frontend for the wkhtmltopdf command. So you need to install this command on your system before you can use the class. On Linux there are two flavours:

  • Statically linked: You install a statically linked version via compose or download it from their homepage. It's self-contained and thus the recommended way to use the class on most webservers.
  • Dynamically linked: This is what you get for example on Ubuntu if you install the wkhtmltopdf package. It will work, but requires an X server which is usually not available on headless webservers. We provide two Xvfb based workarounds below.

Statically linked binary

You can use composer to install the binaries from h4cc/wkhtmltopdf-i386 or h4cc/wkhtmltopdf-amd64. Or you can manually download and unzip the correct package for your architecture from https://code.google.com/p/wkhtmltopdf/. In both cases you have to tell the PHP class where to find the binary.

<?php
$pdf = new WkHtmlToPdf(array(
    'binPath' => '/path/to/your/wkhtmltopdf',
    ...
));

If you put the class somewhere in your $PATH directories it should even get autodetected. You may have to set the correct name of the binary, though (e.g. 'binName' => 'wkhtmltopdf-amd64',).

Dynamically linked binary with Xvfb

If you have to use the dynamically linked binary as it is provided by some Linux versions, you have two options. You can either use

  • the built in Xvfb support or
  • a standalone Xvfb server.

Both require the Xvfb package to be installed on the system and both also have some drawbacks.

Built in Xvfb support

This wraps each call to wkhtmltopdf with xvfb-run. xvfb-run will run any given command in a X environment without all the overhead of a full X session. The drawback with this solution is, that there's still a new session fired up for each an every PDF you create, which will create quite some extra load on your CPU. So this setup is only recommended for low frequency sites.

To enable the built in support you have to set enableXvfb. There are also some options you can set.

<?php
$pdf = new WkHtmlToPdf(array(
    // Explicitly tell wkhtmltopdf that we're using an X environment
    'use-xserver',

    // Enable built in Xvfb support
    'enableXvfb' => true,

    // If this is not set, the xvfb-run binary is autodected
    'xvfbRunBin' => '/usr/bin/xvfb-run',

    // By default the following options are passed to xvfb-run.
    // So only use this option if you want/have to change them.
    'xvfbRunOptions' =>  ' --server-args="-screen 0, 1024x768x24" ',
));

Standalone Xvfb

It's better to start a Xvfb process once and reuse it for all your PHP requests (thanks to Larry Williamson for the original idea). This requires that you have root access to your machine as you have to add a startup script for that process. We have provided an example script for Ubuntu here (Thanks eusonlito). You can put it to /etc/init.d/xvfb and add it to your startup files with update-rc.d xvfb defaults 10. It should be easy to adapt the script for other Linux versions.

If your Xvfb process is running, you just have to tell the class to use this X display for rendering. This is done via an environment variable.

<?php
$pdf = new WkHtmlToPdf(array(
    'use-xserver',                                              
    'procEnv' => array( 'DISPLAY' => ':0' ),  //You can change ':0' to whatever display you pick in your daemon script
));

Full example

For me wkhtmltopdf seems to create best results with smart shrinking turned off. But then I had scaling issues which went away after I set all margins to zero and instead added the margins through CSS. You can also use cm or in in CSS as this is more apropriate for print styles.

<?php
// Create a new WKHtmlToPdf object with some global PDF options
$pdf = new WkHtmlToPdf(array(
    'no-outline',         // Make Chrome not complain
    'margin-top'    => 0,
    'margin-right'  => 0,
    'margin-bottom' => 0,
    'margin-left'   => 0,
));

// Set default page options for all following pages
$pdf->setPageOptions(array(
    'disable-smart-shrinking',
    'user-style-sheet' => 'pdf.css',
));

// Add a page. To override above page defaults, you could add
// another $options array as second argument.
$pdf->addPage('demo.html');

$pdf->send();

demo.html

<!DOCTYPE html>
<head>
</head>
<body>

    <div id="print-area">
        <div id="header">
            This is an example header.
        </div>
        <div id="content">
            <h1>Demo</h1>
            <p>This is example content</p>
        </div>
        <div id="footer">
            This is an example footer.
        </div>
    </div>

</body>
</html>

pdf.css

/* Define page size. Requires print-area adjustment! */
body {
    margin:     0;
    padding:    0;
    width:      21cm;
    height:     29.7cm;
}

/* Printable area */
#print-area {
    position:   relative;
    top:        1cm;
    left:       1cm;
    width:      19cm;
    height:     27.6cm;

    font-size:      10px;
    font-family:    Arial;
}

#header {
    height:     3cm;

    background: #ccc;
}
#footer {
    position:   absolute;
    bottom:     0;
    width:      100%;
    height:     3cm;

    background: #ccc;
}

About

A slim PHP wrapper around wkhtmltopdf with an easy to use and clean OOP interface