PDF - распространённый межплатформенный формат электронных документов, который более двух десятков лет является общепринятым стандартом. Формат отлично подходит для экспорта данных с сайта в виде различных шаблонов, например важной информации для пользователей, сертификатов, документов, отчётов, купонов, инструкций и прочего.
Обзор популярных библиотек на PHP.
На языке PHP написано множество библиотек для генерации PDF, самые популярные из них:
- FPDF - полностью бесплатная библиотека для создания PDF документов с помощью чистого PHP, без использования разметки.
Минимальная версия PHP 5.1.
Основные функции:
- поддержка изображения формата JPEG, PNG и GIF;
- настройка хэдера и футера страницы;
- автоматический перенос строк и разрыв страниц;
- ссылки;
- выравнивание текста;
- изменение цвета элементов документа; - TCPDF - минимальная версия PHP 5.3.
Главные функции библиотеки:
- поддержка изображений JPEG, PNG и SVG по умолчанию;
- всех изображений, поддерживаемых расширением GD и ImageMagick;
- автоматический перенос строк;
- разрыв страниц;
- выравнивание текста;
- режимы рендеринга текста (заливка, обводка и обрезка);
- автоматическая нумерация страниц и групп страниц;
- методы кода XHTML + CSS, JavaScript; - HTML2PDF - API для преобразования готовой HTML разметки в PDF формат. На сайте можно сгенерировать документ вставив ссылку в соответствующее поле. Использует библиотеку TCPDF.
Для использование необходима версия PHP 5.6 или выше, а также установленное расширение mbstring или gd.
Поддерживает все необходимые для работы функции:
- возможность настраивать размеры страницы;
- позволяет персонализировать макет, изменяя шрифты и цвета, отступы;
- инструменты для добавления водяных знаков в документы;
- использует шифрование или пароли для защиты PDF-файлов от несанкционированной печати и копирования; - DOMPDF - конвертер HTML в PDF на основе PHP. Это библиотека преобразует HTML и CSS (включая встроенные стили и внешние таблицы стилей) в PDF-документы.
Для работы требуется PHP версии 7.1 или выше.
Библиотека поддерживает множество функций, таких как:
- CSS 2.1 и несколько свойств CSS3, включая правила @import, @media и @page;
- большинство атрибутов HTML;
- поддержка изображений gif, png (8, 24 и 32 бит с альфа-каналом), bmp и jpeg;
- отсутствие зависимости от сторонних PDF-библиотек.
Пример генерации PDF с помощью пакета DOMPDF
Инициализация проекта
Что бы инициализировать проект, воспользуемся командой пакетного менеджера Composer - “composer init”, для этого выполним её через терминал в корне нашего проекта.
После стандартной процедуры ответа на все вопросы предлагаемые композером создадим файл index.php в корне проекта, для простоты вся логика работы PDF генератора будет находиться именно здесь.
Также создадим папку resources, для хранения шаблонов с HTML разметкой, и папку storage для хранения результатов.
Установка DOMPDF
1) COMPOSER - Библиотеку можно установить, как обычный пакет PHP с помощь команды пакетного менеджера, которая установит все необходимые зависимости.
composer require dompdf/dompdf
2) GIT - можно склонировать репозиторий или просто скачать библиотеку архивом и поместить его содержимое в проект.
git clone https://github.com/dompdf/dompdf/ .
В этом случае что бы использовать классы DOMPDF в коде PHP, необходимо подключать файл автозагрузчика пакета, который расположен по пути dompdf/autoload.inc.php.
Принцип работы с DOMPDF
Создание любого документа PDF происходит в несколько шагов:
- Настройка необходимых параметров таких как размер и ориентация бумаги, пути к файлам шрифтов и кеша, настройка доступа к удалённым ресурсам и прочее.
- Генерация представления документа.
- Вызов метода render для запуска самого процесса генерации документа.
- Получение результатов генерации документа.
Конфигурация DOMPDF
Основным классом библиотеки является класс Dompdf\Dompdf, он содержит методы для загрузки html разметки, генерации документа и получения результата.
В роли конфигуратора выступает класс настроек Dompdf\Options, который можно передать как опциональный параметр конструктора основного класса Dompdf.
В файле index.php подключим автозагрузчик созданный пакетным менеджером и импортируем необходимые классы:
require 'vendor/autoload.php';
use Dompdf\Dompdf;
use Dompdf\Options;
Основные методы класса настроек:
setChroot - все локальные файлы, открытые dompdf, должны находиться в каталоге заданном в этом методе. Не рекомендуется устанавливать это значение в «/», так как это может позволить dompdf читать любые файлы на сервере, а это не безопасно. Далее в шаблоне все пути к локальным файлам должны быть прописаны относительно указанной директории, в нашем случае это раннее созданная папка resources.
setTempDir - путь сохранения временных файлов для загрузки удаленных изображений. Указанный каталог должен быть доступен для записи исполняющемуся процессу.
setIsRemoteEnabled - включение удалённого доступа к файлам. Если для этого параметра установлено значение true, DOMPDF будет получать доступ к изображениям и файлам CSS удаленных сайтов. Что бы данный метод работал необходимо чтобы в конфигурации PHP параметр allow_url_fopen также был установлен в значение true.
setAllowedRemoteHosts - список разрешенных удаленных хостов. Каждое значение массива должно быть именем хоста, который будет использоваться для фильтрации ресурсов, которые можно загружать. Если isRemoteEnabled имеет значение FALSE, метод не будет иметь никакого эффекта. По умолчанию значение равняется NULL, которое разрешает любой удаленный хост.
setPdfBackend - используемое расширение для рендеринга PDF. Допустимые настройки: «PDFLib», «CPDF», «GD» и «auto». «Auto» будет проверять наличие расширения PDFLib и использовать его, если оно найдено, в противном случае будет использоваться CPDF.
setFontDir - местоположение каталога, в котором DOMPDF будет хранить шрифты и метрики шрифтов. Этот каталог должен существовать и быть доступен для записи.
setDefaultPaperSize - размер бумаги, для большинства стран по умолчанию "а4".
Все допустимые размеры можно увидеть в переменной класса \Dompdf\Adapter\CPDF::PAPER_SIZES.
setDefaultPaperOrientation - ориентация бумаги по умолчанию. Доступные варианты книжная или альбомная.
setLogOutputFile - лог-файл для записи содержимого буфера вывода после выполнения преобразования HTML в PDF, может быть полезен для отладочной информации.
Пример конфигурации Dompdf\Options()
define('ROOT', 'D:/OSPanel/domains/pdf/');
$options = new Options();
$options->setChroot(ROOT . 'resources/');
$options->setTempDir(ROOT . 'storage/tmp');
$options->setIsRemoteEnabled(true);
$options->setFontDir(ROOT . 'resources/fonts/');
$options->setDefaultPaperSize('a4');
$options->setDefaultPaperOrientation('portrait');
$dompdf = new Dompdf($options);
Пример генерация PDF из HTML
Метод класса-генератора принимает уже готовую HTML разметку в виде строки, поэтому этот этап никак не зависит от библиотеки и для генерации разметки может быть использован любой удобный способ, будь то шаблонизатор, строковая переменная PHP или буферизация вывода.
Мы воспользуемся третьим вариантом и поместим всё содержимое файла resources/pdf-example.php в переменную $html:
ob_start();
require 'resources/pdf-example.php';
$html = ob_get_contents();
ob_end_clean();
Использование CSS в DOMPDF имеет некоторые ограничения:
- ячейки таблицы не могут быть постраничными, то есть строка таблицы должна умещаться на одной странице;
- не поддерживает CSS Flexbox;
- не поддерживает CSS Grid;
- один экземпляр Dompdf не следует использовать для рендеринга более одного HTML-документа, поскольку сохраняющиеся артефакты рендеринга могут повлиять на будущие результаты;
- использование «необработанных» SVG не работает, вам нужно либо создать ссылку на внешний SVG-файл, либо использовать DataURI следующим образом:
$html = '<img src="data:image/svg+xml;base64,' . base64_encode($svg) . '" ...>';
Подключение шрифтов
DOMPDF по умолчанию поддерживает только следующие шрифты:
- Helvetica (Normal, Bold, Oblique, and BoldOblique variants)
- Times (Normal, Bold, Oblique, and BoldOblique variants)
- Symbol
- ZapfDingbats
- Courier (Normal, Bold, Oblique, and BoldOblique variants)
Эти шрифты поддерживают только кодировку Windows ANSI.
Чтобы в PDF-файле отображались символы, недоступные в Windows ANSI, необходимо указать внешний шрифт, который будет встроен в PDF-файл.
DOMPDF встроит любой указанный шрифт в PDF-файл, который был предварительно загружен или указан в правиле CSS @font-face.
Рассмотрим оба способа добавления внешних шрифтов.
- Скачаем гугл-шрифт Jost-Regular - https://fonts.google.com/specimen/Jost
Расположим его по пути resources/fonts/Jost-Regular.ttf
Затем подключим загруженный шрифт через правило @font-face в теги <style> шаблона:
@font-face { font-family: "Jost-Regular"; font-style: normal; font-weight: normal; src: url("resources/fonts/Jost-Regular.ttf") format('truetype'); }
Теперь в CSS свойствах есть возможность указывать новый шрифт:
body { font-family: 'Jost-Regular'; }
- Подключить шрифт напрямую через ссылку в теги <link>:
<link href="https://fonts.googleapis.com/css2?family=Montserrat&display=swap" rel="stylesheet" />
И затем также указывать семейство шрифтов в CSS свойствах:
body { font-family: 'Montserrat'; }
Пример разметка HTML документа для DOMPDF
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://fonts.googleapis.com/css2?family=Montserrat&display=swap" rel="stylesheet" />
<title>PDF Example</title>
<style>
@font-face {
font-family: "Jost-Regular";
font-style: normal;
font-weight: normal;
src: url("resources/fonts/Jost-Regular.ttf") format('truetype');
}
body {
font-family: 'Montserrat';
}
table {
font-family: 'Helvetica';
}
td, th {
padding: 5px;
}
tr:nth-child(even) {
background-color: #BFE7FF;
}
tr:nth-child(odd) {
background-color: #F5F8FA;
}
img {
width: 200px;
height: 200px;
}
</style>
</head>
<body>
<img src="https://ventiontech.com/cdn/shop/products/vention-black-vention-bluetooth-5-3-earphones-tws-true-wireless-headphones-usb-c-aac-sbc-stereo-sports-earbuds-with-mic-hi-fi-headset-35952785981606.jpg?v=1698226840" />
<img src="resources/img/image.jpg" />
<h1>PRODUCT #9823832</h1>
<table>
<tr>
<td><b>Name</b></td>
<td>Earphone</td>
</tr>
<tr>
<td><b>Price</b></td>
<td>$40.00</td>
</tr>
<tr>
<td><b>Description</b></td>
<td>Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur quam excepturi omnis veniam odio saepe...</td>
</tr>
<tr>
<td><b>Rate</b></td>
<td>4.6</td>
</tr>
</table>
</body>
</html>
Рендеринг документа PDF на PHP (DOMPDF)
Для того что бы загрузить полученную разметку у класса Dompdf существует метод loadHtml. Он принимает два аргумента строку HTML для загрузки и метод кодировки. По умолчанию второй параметр равен null, в таком случае используется кодирование указанное в теге <meta>.
Ошибки парсинга сохраняются в глобальном массиве $_dompdf_warnings.
Помимо загрузки строки в dompdf можно воспользоваться методам loadHtmlFile, который идентичен в использовании предыдущему методу, но в качестве первого параметра принимает имя файла или URL для загрузки.
После того как разметка загружена следует вызвать метод render который выполняет преобразованию HTML в PDF:
try {
$dompdf->loadHtml($html);
$dompdf->render();
} catch (Exception $e) {
print_r($e->getMessage());
}
Получение результата рендера PDF
Библиотека DOMPDF предоставляет удобный метод для вывода полученного результата сразу в браузер - этот метод называется stream и принимает он два параметра имя выводимого файла и массив с дополнительными опциями.
Массив опций допускает два ключа:
- compress - применить сжатие потока контента. По умолчанию 1;
- attachment - устанавливает для HTTP-заголовка «Content-Disposition:» значение «attachment», которое заставляя браузер открыть диалоговое окно загрузки. По умолчанию 1
Если необходимо сохранить файл на диск или стандартный метод вывода в браузер не подходит можно получить PDF документ в виде строки методом output, который принимает опциональный массив с одним ключом compress.
Далее этот результат можно сохранить в файл любым способом, например функцией file_put_contents:
// Выведет PDF документ в браузер
$dompdf->stream('pdf', ['Attachment' => 0]);
// Создаст PDF документ по указанному пути
file_put_contents('storage/results/' . time() . '.pdf', $pdf);
Готовый пример код PHP для генерации PDF документа
<?php
ini_set('allow_url_fopen', 'On');
require 'vendor/autoload.php';
use Dompdf\Dompdf;
use Dompdf\Options;
define('ROOT', 'D:/OSPanel/domains/pdf/');
$options = new Options();
$options->setChroot(ROOT . 'resources/');
$options->setTempDir(ROOT . 'storage/tmp');
$options->setIsRemoteEnabled(true);
$options->setFontDir(ROOT . 'resources/fonts/');
$options->setDefaultPaperSize('a4');
$options->setDefaultPaperOrientation('portrait');
$dompdf = new Dompdf($options);
ob_start();
require 'resources/pdf-example.php';
$html = ob_get_contents();
ob_end_clean();
try {
$dompdf->loadHtml($html);
$dompdf->render();
} catch (Exception $e) {
print_r($e->getMessage());
}
// Выведет PDF документ в браузер
$dompdf->stream('pdf', ['Attachment' => 0]);
// Создаст PDF документ по указанному пути
file_put_contents('storage/results/' . time() . '.pdf', $pdf);