DOMPDF – экспорт данных из PHP в PDF

С помощью библиотеки DOMPDF можно создавать PDF файлы из HTML кода. Нужно только сверстать некий HTML шаблон и передать его DOMPDF и уже на выходе получить сгенерированный PDF файл. Но не надо забывать и то, что эта библиотека не движок для обработки веб-страниц, а значит и шаблоны должны быть сверстаны с использованием самых базовых средств: HTML тегов и CSS стилей. Хотя разработчики заявляют, что их библиотека поддерживает стандарты CSS 2.1 и даже некоторые свойства CSS 3. С полным их перечнем можно ознакомиться здесь. Есть, кстати, один минус — она является довольно «прожорливой» к оперативной памяти. Поэтому возможно придется задуматься об аренде виртуального выделенного сервера. Но это зависит от содержания и объема планируемых PDF документов. С другой стороны она вам может помочь сэкономить много времени на разработку различных отчетов в формате PDF.Читая различную документацию по DOMPDF, а ее немного и то в основном больше информации в виде ответов на заданные вопросы. Я заметил, что ее используют для более тривиальных задач. Ну, к примеру, ответа на вопрос: как задать номер стартовой страницы для документа? Мной получено не было.Сейчас я вам хочу рассказать о тех «подводных камнях», с которыми мне пришлось столкнуться. И поверьте, я потерял много времени. Потерял бы еще больше, если бы мне не дал пару советов один добрый человек. Уже имевший опыт по работе с данной библиотекой.Представляю перечень проблем, с которыми мне пришлось столкнуться: отсутствие необходимых каталогов с файлами (не полная сборка); частично рабочая версия библиотеки; наличие бага при попытке установки номера страницы документа (номер стартовой страницы); наличие в конце документа пустой страницы; не полное заполнение страницы текстом (иногда оставалось много пустого места). Как видно из всего выше сказанного, в этой библиотеке имеется достаточно неприятных багов, но если постараться, то с ней можно «договориться».Установка библиотекиСаму библиотеку берем вот здесь. Я, к сожалению, не могу сказать (как обычно говорят в таких случаях), что необходимо скачать самую новую версию. Далее я объясню почему. Но я все-таки надеюсь, что со временем существующие в последней версии баги будут устранены. После получения архива с библиотекой, распакуйте его в нужную вам на сервере директорию.В корневом каталоге библиотеки DOMPDF находиться файл конфигурации — dompdf_config.inc.php. В нем присутствуют базовые настройки библиотеки. Нас здесь интересуют следующие три: значением директивы DOMPDF_DEFAULT_PAPER_SIZE содержит значение размера листа бумаги (a4, letter и т.д.); в директиве DOMPDF_DPI в численном выражении указывается качество детализации документа. По умолчанию оно равно 96; значение директивы DOMPDF_TEMP_DIR следует изменить на содержащееся значение в PHP директиве upload_tmp_dir, но только в том случае, если значение, возвращенное PHP функцией sys_get_temp_dir, будет отличным от значения этой PHP директивы. С полным перечнем возможных настроек можно ознакомиться здесь. Минимальная конфигурация сервера должна быть следующей: PHP Version 5.0; DOMDocument extension; PCRE; Zlib; MBString extension; GD. Так же рекомендуется установить программу GMagick или IMagick ну и соответственно подключить ее через расширение к PHP. Здесь прослеживается такая вот особенность: что якобы установка одной из рекомендуемых программ позволит лучше работать с прозрачностью изображений в формате PNG. Но на практике выяснилось следующее: если на сервере не установлена ни одна из программ, то прозрачность изображений в формате PNG вообще не обрабатывается. Исключение было для Denwera 3. Для PHP 5.3 входящим в пакет Denwera 3 необходимости в установке ни в одной из двух данных программ не возникло.Установка шрифтов Изначально в библиотеке присутствует набор базовых шрифтов, однако среди них нет тех, которые поддерживали бы кириллицу. Поэтому если нужны кириллические шрифты или есть необходимость в расширении имеющегося множества уже готовых шрифтов, то придется заняться их установкой. И в этом нет ничего сложного. Устанавливать можно шрифты как TrueType (*.ttf) так и OpenType (*.otf). Для работы нам понадобится PHP скрипт load_font.php, который располагается в корне каталога библиотеки DOMPDF. Запуск данного скрипта необходимо производить из командной строки и на вход он принимает следующие параметры: font_family — имя шрифта; n_file — файл *.ttf или *.otf; {b|i|bi}_file — файлы соответствующие стилям шрифта (bold, italic, bold-italic). Примеры: ./load_font.php slkscr /usr/share/fonts/truetype/slkscr.ttf ./load_font.php Arial /mnt/c_drive/WINDOWS/Fonts/arial.ttf Для демонстрации произведем установку шрифта «roboto». Предположим что каталог со шрифтом «roboto» и его стилями находится в директории «D:\font». Соответственно если нам нужен только шрифт со стилем «normal», то необходимо запустить скрипт со следующими параметрами: ./load_font.php Roboto D:\font\Roboto-Regular.ttf. Но если требуется установить шрифт «roboto» со всеми четырьмя его стилями (normal, bold, italic и bold-italic), то вызов скрипта уже будет иметь другой вид: ./load_font.php Roboto D:\font\Roboto-Regular.ttf D:\font\Roboto-Bold.ttf D:\font\Roboto-Italic.ttf D:\font\Roboto-BoldItalic.ttf. Обратите внимание на порядок передачи параметров скрипту для одновременного создания шрифта «roboto» с его четырьмя стилями. Первым передается путь к файлу шрифта со стилем «normal», затем «bold» и т.д. Этот порядок нарушать ни в коем случае нельзя.Создание шаблона для DOMPDF Шаблон представляет обычную HTML страницу с добавлением некоторых новых свойств CSS, которые необходимы для работы самой библиотеки. Весь исходный код шаблона я здесь приводить не стану, так как в этом нет необходимости. Тем более что к статье прилагаются все необходимые файлы. Кстати в шаблоны можно встраивать код на PHP и JavaScript. В нашем случае в шаблоне будет располагаться шесть меток: метка для устанавливаемого номера страницы {start-page}, метка с кодом цвета {color} для подвала страницы, метка {page-1} для текста на первой странице, метка {page-2} для текста на второй странице и две метки {label-1} и {label-2} для вывода информационного текста в подвал. Также будет присутствовать встроенный скрипт на PHP для примитивного рисования и вывода нумерации страниц. Данные, которые могут занимать более одной страницы необходимо заключать в блок. Можно конечно этого не делать, но тогда не будет возможности вставлять разрывы страниц, да и текст может не равномерно заполнять страницу. Для вставки разрыва страницы, следует в стилях этого блока прописать одно из следующих свойств: page-break-after: always — вставляет разрыв после страницы; page-break-before: always — вставляет разрыв перед страницей; page-break-inside: auto — здесь имеется ввиду, что DOMPDF сама «примет» решение; page-break-inside: avoid — запрещает разрыв внутри элемента. Теперь осталось сделать нумерацию страниц. Для этого требуется написать небольшой PHP скрипт и вставить его в шаблон. if (isset ($pdf)) { /* * Открытие объекта для сохранения всех * операций рисования */ $footer = $pdf→open_object (); // Получаем ширину страницы $p_width = $pdf→get_width (); // Получаем высоту страницы $p_height = $pdf→get_height (); // Устанавливаем номер страницы $pdf→set_page_number ({start-page}); $font = Font_Metrics: get_font («Roboto», «normal»); //$text_w = $pdf→get_text_width ($PAGE_NUM, «Roboto», 14); /* * Сами (для примера) рассчитываем ширину текста (номера страницы) * иначе есть видимо неустранимый пока баг */ $text_w = 8.036; // Получаем высоту текста (номера страницы) $text_h = $pdf→get_font_height («Roboto», 14); $x = $p_width — $text_w — 15; $y = $p_height — $text_h / 2 — 20; // Выводим текст на страницу $pdf→page_text ($x, $y,»{PAGE_NUM}», $font, 14, array (255, 255, 255)); // Рисуем окружность $radius = min ($text_w * 1.5, $text_h * 1.5); $color = array (0, 0.607, 0.901); $pdf→circle ($x + $text_w / 2, $y + $text_h / 2, $radius, $color);

// закрытие текущего объекта $pdf→close_object (); /* * Добавляет объект на каждую страницу * также можно добавлять на четную или нечетную: «even» или «odd») */ $pdf→add_object ($footer, «all»); } Нумерацию можно сделать и другим способом. Создаете CSS стиль: footer .page: after { content: counter (page); } А затем в необходимое вам в HTML коде место вставить конструкцию: Но только во втором варианте, нельзя задать номер стартовой страницы. Возможно, нам понадобиться не начинать нумерацию с единицы, а к примеру с двойки и т.д. В таком случае подойдет только использование первого метода.

Примечание: При работе с графикой во встроенных скриптах, значение цвета каждой из RGB составляющих должно находиться в диапазоне 0 — 1. Т.е. каждую составляющую цвета в формате RGB требуется разделить на 255.

Создание модуля для экспорта данных Осталось самое простое — это сделать экспорт данных. Но есть в библиотеке и еще один небольшой баг. Он заключается в том, что если нам понадобиться сгенерировать несколько файлов, то нужно для каждой итерации создавать экземпляр объекта класса DOMPDF заново, иначе вы получите сообщение об ошибке. Ниже приведен исходный код модуля: define ('ROOT_DIR', dirname (__FILE__));

define ('BASE_PATH', ROOT_DIR. '/template/icon');

define ('TEMPLATE', ROOT_DIR. '/template/main.html');

// Подключаем файл с конфигурацией DOMPDF require_once (ROOT_DIR. '/dompdf/dompdf_config.inc.php');

// Загрузка шаблона if (@file_exists (TEMPLATE)) $template = file_get_contents (TEMPLATE);

/* * Номер текущей страницы * если требуется сгенерировать несколько документов */ $current_page = 1;

// Массив с метками и их значениями для шаблона $signs = array ( 'color' => '#0080C0', 'page-1' => 'Страница 1', 'page-2' => 'Страница 2', 'label-1' => 'site.com', 'label-2' => 'info@site.com', 'start-page' => $current_page);

// Замена меток в шаблоне их значениями foreach ($signs as $key => $value) $template = str_replace ('{' . $key. '}', $value, $template);

$pdf = new DOMPDF (); // Устанавливаем путь к директории с изображениями и CSS стилями $pdf→set_base_path (BASE_PATH); // Загружаем шаблон $pdf→load_html ($template); // Генерируем PDF файл $pdf→render (); // Получаем данные в формате PDF $data = $pdf→output ();

/* * Увеличили счетчик числа сгенерированных страниц * на число страниц текущего документа */ $current_page = $current_page + $pdf→get_canvas ()→get_page_count (); // Сохраняем PDF файл file_put_contents (ROOT_DIR.»/example.pdf», $data); В результате должен получиться PDF файл следующего образца:

07b9e98483ff43cca87ac22c02dfd272.jpg Выводы Хотя в данной библиотеке и достаточно различных недоработок, но она того стоит. Во-первых, она бесплатная и это уже должно закрыть все претензии к разработчикам. Во-вторых, я думаю, что в ближайшее время если не все, то многие баги будут устранены. Единственная проблема в том, что как я уже писал выше, что данная библиотека используется больше для тривиальных задач, поэтому мало есть описания для решения различных возникающих проблем.Все используемые файлы: PDF, шаблон и модуль экспорта можно скачать отсюда.

© Habrahabr.ru