Let's Encrypt Auto-Renewal Setup and Certificate Expiry Alerts

12 min read 2,385 words
HTTPS Certificate Management with Let's Encrypt: Auto-Renewal and Certificate Expiry Alerts featured image

PDF Generation in PHP: Tools and Approaches That Produce Quality Output

Generating PDF documents from web applications is a common requirement for invoice generation, report creation, printable receipts, and automated documentation. PHP offers several approaches to this problem, each with distinct advantages and limitations. Choosing the right method early saves significant refactoring time later.

This guide covers the most practical tools available for PHP PDF generation, with working examples and guidance on when each approach works best.

Why PDF Generation Matters for Business Applications

Businesses need PDFs for documents that must look consistent across all devices and platforms. An invoice generated as HTML might render differently in Chrome versus Safari, or break entirely on a mobile device. A PDF preserves your formatting exactly, ensuring clients see what you intended regardless of how they open the document.

Beyond consistency, PDFs serve legal and professional purposes. Official documents, contracts, and financial statements carry more weight when presented as PDFs rather than web pages. The format is universally recognised and difficult to alter after creation.

Automating PDF generation also reduces manual work. Instead of exporting documents manually, your application can generate hundreds of invoices or reports on demand without human intervention.

Dompdf: A PHP-First Solution

Dompdf is a PHP library that converts HTML and CSS into PDF documents. It parses your HTML, applies CSS styling, and renders the result as a PDF file. For many PHP developers, this is the most straightforward approach because it leverages existing HTML knowledge.

Installing Dompdf via Composer

The easiest way to install Dompdf is through Composer:

composer require dompdf/dompdf

This pulls the latest stable version and its dependencies into your project.

Basic Dompdf Usage Example

Here is a simple example showing how to generate a PDF from HTML:

require_once 'vendor/autoload.php';

use Dompdf\Dompdf;

$dompdf = new Dompdf();

// Simple HTML content
$html = '
<html>
<head>
<style>
body { font-family: Arial, sans-serif; }
h1 { color: #333; }
table { width: 100%; border-collapse: collapse; }
td, th { border: 1px solid #ddd; padding: 8px; }
</style>
</head>
<body>
<h1>Invoice #12345</h1>
<p>Generated on: ' . date('Y-m-d') . '</p>
<table>
<tr><th>Item</th><th>Qty</th><th>Price</th></tr>
<tr><td>Web Development</td><td>10</td><td>£750.00</td></tr>
<tr><td>Hosting Setup</td><td>1</td><td>£150.00</td></tr>
</table>
</body>
</html>';

$dompdf->loadHtml($html);
$dompdf->setPaper('A4', 'portrait');
$dompdf->render();
$dompdf->stream('invoice.pdf', ['Attachment' => true]);

This generates a simple invoice PDF and forces a download. Change the Attachment parameter to false to display the PDF inline in the browser instead.

Dompdf Limitations

Dompdf has a CSS compatibility level roughly equivalent to CSS 2.1. It handles most common styling well, but complex layouts with floating elements, advanced positioning, or newer CSS properties may not render correctly. If your design relies heavily on flexbox or grid layouts, test early to confirm Dompdf handles your specific use case.

External resources such as images, fonts, or stylesheets referenced via absolute URLs load correctly. Relative URLs work if you set the appropriate base path:

$dompdf->setOptions([
    'rootPath' => '/var/www/myapp/public/'
]);

When Dompdf Works Well

  • Invoices and receipts: Structured documents with tables, headers, and basic styling.
  • Reports with tables: Data-heavy documents where layout is relatively linear.
  • Simple letters and templates: Documents that do not require complex positioning.
  • Developer-friendly projects: When your team is more comfortable with HTML and CSS than PDF-specific APIs.

wkhtmltopdf: High-Quality Rendering via WebKit

wkhtmltopdf uses the Qt WebKit rendering engine to convert HTML to PDF. Because it renders pages the same way a web browser does, it handles modern CSS, JavaScript, and complex layouts with greater accuracy than pure PHP libraries.

Installation

wkhtmltopdf is a command-line tool that must be installed on your server. On Ubuntu or Debian, install it with:

sudo apt update
sudo apt install wkhtmltopdf

For other operating systems, download the appropriate package from the wkhtmltopdf website.

Calling wkhtmltopdf from PHP

Once installed, you can call wkhtmltopdf directly from PHP using the exec or shell_exec functions:

<?php
$htmlFile = '/tmp/document.html';
$outputFile = '/var/www/myapp/public/invoices/output.pdf';

// Render the HTML to a temporary file first
file_put_contents($htmlFile, $htmlContent);

$command = "wkhtmltopdf --page-size A4 --orientation Portrait --print-media-type $htmlFile $outputFile";
$output = shell_exec($command . ' 2>&1');

// Check if the file was created successfully
if (file_exists($outputFile)) {
    echo "PDF created successfully at $outputFile";
} else {
    echo "PDF generation failed: " . $output;
}
?>

Useful wkhtmltopdf Options

wkhtmltopdf offers many command-line options for controlling output quality:

  • Page size: --page-size A4 or --page-size Letter
  • Orientation: --orientation Portrait or --orientation Landscape
  • Margins: --margin-top 20mm --margin-bottom 20mm --margin-left 15mm --margin-right 15mm
  • Print media: --print-media-type forces the PDF to use print stylesheets
  • Header and footer: --header-html url and --footer-html url
  • Zoom: --zoom 1.2 adjusts rendering scale

Handling Headers and Footers

Adding dynamic headers and footers requires separate HTML files or URLs:

$headerHtml = '<html><body style="font-size:10px; text-align:center;">Company Name - Invoice</body></html>';
$footerHtml = '<html><body style="font-size:10px; text-align:center;">Page <span class="page">/</span> <span class="topage"></span></body></html>';

file_put_contents('/tmp/header.html', $headerHtml);
file_put_contents('/tmp/footer.html', $footerHtml);

$command = "wkhtmltopdf --header-html /tmp/header.html --footer-html /tmp/footer.html $htmlFile $outputFile";
shell_exec($command);

wkhtmltopdf Limitations

The main drawback is that wkhtmltopdf requires a graphical environment to render pages. On headless servers without a display, you need Xvfb (a virtual framebuffer) to run wkhtmltopdf:

sudo apt install xvfb
xvfb-run wkhtmltopdf --page-size A4 input.html output.pdf

Additionally, wkhtmltopdf is slower than pure PHP libraries because it launches a separate process for each PDF. For high-volume generation, consider caching or queuing systems.

Snappy: A Modern Wrapper Around wkhtmltopdf

Snappy is a PHP library that provides a cleaner API for wkhtmltopdf. It handles process management, temporary files, and options more elegantly than raw shell commands.

Installing Snappy

composer require knplabs/knp-snappy

Basic Snappy Usage

require_once 'vendor/autoload.php';

use Knp\Snappy\Pdf;

$snappy = new Pdf('/usr/bin/wkhtmltopdf');

$snappy->setOption('page-size', 'A4');
$snappy->setOption('orientation', 'Portrait');
$snappy->setOption('print-media-type', true);
$snappy->setOption('margin-top', 15);
$snappy->setOption('margin-bottom', 15);

header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="document.pdf"');

echo $snappy->getOutputFromHtml($htmlContent);

Snappy reduces boilerplate code significantly and makes your PDF generation logic easier to maintain.

TCPDF: For Maximum Control Over PDF Structure

TCPDF is a PHP library that generates PDFs without external dependencies. It has its own drawing API, which gives you precise control over every element in the document.

TCPDF suits scenarios where you need to create PDFs programmatically with custom graphics, barcodes, precise positioning, or non-standard page layouts. It handles Unicode text well, making it suitable for documents in multiple languages.

TCPDF Example

require_once 'vendor/autoload.php';

use TCPDF;

$pdf = new TCPDF(PDF_PAGE_ORIENTATION, 'mm', PDF_PAGE_FORMAT, true, 'UTF-8', false);

$pdf->AddPage();
$pdf->SetFont('helvetica', 'B', 16);
$pdf->Cell(0, 10, 'Invoice #12345', 0, 1, 'C');
$pdf->SetFont('helvetica', '', 12);
$pdf->Ln(10);
$pdf->Cell(0, 10, 'Generated: ' . date('Y-m-d'), 0, 1, 'L');

$pdf->SetFont('helvetica', '', 10);
$pdf->Ln(10);
$pdf->MultiCell(100, 10, "Web Development\nHours: 10\nRate: £75/hour\nTotal: £750.00", 1, 'L');

$pdf->Output('invoice.pdf', 'I');

When TCPDF Is the Right Choice

  • Custom graphics: Drawing charts, diagrams, or geometric shapes directly in the PDF.
  • Barcodes and QR codes: Built-in support for various barcode formats.
  • Multi-language documents: Excellent Unicode support for non-Latin character sets.
  • Legacy systems: Environments where installing external tools is not possible.

Choosing the Right PDF Generation Approach

The best tool depends on your specific requirements. Consider these factors when making your decision.

Document Complexity

For simple documents with straightforward layouts, Dompdf is often sufficient and requires the least setup. For complex documents with modern CSS, multi-column layouts, or precise typography, wkhtmltopdf or Snappy produce more reliable results.

Server Environment

Pure PHP libraries like Dompdf and TCPDF run anywhere Composer is available. wkhtmltopdf requires installation on the server and, ideally, a graphical environment or Xvfb on headless systems. If you do not have server access or control over the hosting environment, stick with PHP-only solutions.

Performance Requirements

Dompdf and TCPDF run entirely in PHP, which is faster for small volumes. wkhtmltopdf launches a separate process per document, which adds overhead. For generating hundreds of PDFs in batch, pure PHP libraries are more efficient. For occasional on-demand generation, the performance difference is negligible.

Maintenance and Updates

Dompdf and Snappy have active communities and receive regular updates. TCPDF is well-maintained but has a steeper learning curve. wkhtmltopdf development has slowed in recent years, though it remains stable and widely used.

Best Practices for PHP PDF Generation

  • Test with real content: Generate sample PDFs with actual data before committing to a tool. Render differences become obvious quickly.
  • Separate HTML templates from logic: Keep your HTML templates clean and manage data separately. This makes styling easier and keeps your code organised.
  • Use print stylesheets: If using wkhtmltopdf, a dedicated print stylesheet can simplify PDF-specific styling without affecting screen rendering.
  • Handle fonts carefully: Custom fonts may not embed correctly across all tools. Test font rendering on different systems.
  • Cache generated PDFs: If the same document is requested repeatedly, cache the PDF file rather than regenerating it each time.
  • Set appropriate timeouts: Complex PDFs can take several seconds to generate. Adjust script timeouts accordingly.

Common Problems and How to Avoid Them

Missing Images

Images fail to appear when file paths are incorrect or when external URLs are blocked. Always use absolute paths or set the base path explicitly. Verify that image URLs are accessible from the server, not just from your local machine.

Inconsistent Font Rendering

Fonts can render differently across PDF libraries. Embed fonts directly when possible to ensure consistent output. For Dompdf, use web-safe fonts or embed custom fonts via CSS @font-face.

Memory Issues with Large Documents

Generating multi-page PDFs with many images can consume significant memory. Increase PHP memory limits for these operations:

ini_set('memory_limit', '256M');

Slow Generation on Shared Hosting

Shared hosting environments often restrict process execution, making wkhtmltopdf unusable. In these cases, use Dompdf or TCPDF. Alternatively, consider generating PDFs on a separate server or using an external API service.

Securing Your PDF Generation Setup

PDF generation can introduce security risks if not handled carefully. Temporary files created during rendering may expose sensitive data if left in accessible directories. Use secure temporary directories with appropriate permissions:

// Use PHP's sys_get_temp_dir() for secure temporary storage
$tempDir = sys_get_temp_dir();

// Generate a unique filename to prevent collisions
$tempFile = tempnam($tempDir, 'pdf_');
unlink($tempFile); // Remove the file, keep the directory path

Clean up temporary files immediately after generating the PDF. Never leave rendered HTML containing sensitive information in publicly accessible locations.

If your PDF generation processes user-submitted HTML, sanitise the input to prevent cross-site scripting or other attacks that could affect the server during rendering.

Related practical reading

These related guides can help you connect this topic with the wider website, server, security, and support decisions around it.

Getting Started with PHP PDF Generation

PHP offers several capable approaches to PDF generation, each suited to different requirements. Dompdf works well for HTML-centric workflows and straightforward documents. wkhtmltopdf delivers superior rendering quality for complex layouts. TCPDF provides maximum control for programmatically generated graphics and multi-language documents.

Start with the simplest tool that meets your needs. Generate sample documents with real content to verify output quality before committing to a specific approach. As your requirements grow more complex, you can migrate to more powerful tools without replacing your entire workflow.

If you need help evaluating which PDF generation approach fits your application, or if you are experiencing specific issues with an existing setup, you can get in touch with details of your application, document requirements, and hosting environment.

Frequently Asked Questions

Which PHP PDF library is best for invoices?
For most invoice templates with standard layouts, Dompdf provides the simplest integration. If your invoices use complex CSS layouts, wkhtmltopdf via Snappy produces more reliable results. TCPDF is appropriate when you need precise control over PDF structure or multi-language support.
Can I generate PDFs without installing external tools on the server?
Yes. Dompdf and TCPDF are pure PHP libraries that require no external dependencies beyond Composer. They work on any hosting environment that supports PHP and allows external libraries. wkhtmltopdf requires server-level installation and is not suitable for restricted shared hosting.
How do I add headers and footers to PDFs in PHP?
In Dompdf, you add headers and footers by including HTML elements in your template with specific positioning. In wkhtmltopdf, use the --header-html and --footer-html options pointing to separate HTML files. TCPDF has built-in methods like SetHeaderData and SetFooterData for this purpose.
Why do images not appear in my generated PDF?
Images typically fail to appear due to incorrect file paths, accessibility issues, or unsupported image formats. Use absolute paths for images and verify the server can access those paths. Ensure images are in formats supported by your PDF library, such as JPEG, PNG, or GIF.
How can I speed up PDF generation in PHP?
For high-volume scenarios, consider caching generated PDFs rather than regenerating them on each request. On the server side, increase PHP memory limits and execution timeouts. Using a pure PHP library like Dompdf instead of wkhtmltopdf can reduce process overhead for smaller documents.
Is wkhtmltopdf still maintained?
wkhtmltopdf development has slowed in recent years, but the project remains functional and widely deployed. Many developers continue to use it successfully. If you need the highest rendering quality and can manage the server requirements, wkhtmltopdf remains a solid choice.