Skip to content

Продвинутые функции

Помимо базового рендеринга HTML-в-PDF, пакет Artisan предоставляет утилиты для объединения документов, внедрения глобальных стилей, захвата скриншотов и тонкой настройки поведения Chrome.

Объединение PDF

Класс PdfMerger объединяет несколько HTML-источников в один PDF-документ. Каждый источник рендерится как отдельная секция, и результаты конкатенируются по порядку.

php
use Yeeefang\TcpdfNext\Artisan\PdfMerger;
use Yeeefang\TcpdfNext\Artisan\RenderOptions;

$merger = PdfMerger::create();

$merger
    ->addHtml('<h1>Cover Page</h1><p>Annual Report 2026</p>')
    ->addFile('/templates/chapter-1.html')
    ->addFile('/templates/chapter-2.html')
    ->addUrl('https://charts.example.com/annual-summary')
    ->addHtml('<h1>Appendix</h1><p>Supporting data tables.</p>');

$merger->save('/reports/annual-2026.pdf');

Опции для каждой секции

Каждая секция может иметь собственные RenderOptions. Например, обложка в альбомной ориентации, а главы в портретной.

php
$coverOptions = RenderOptions::create()
    ->setPageSize('A4')
    ->setLandscape(true)
    ->setPrintBackground(true);

$chapterOptions = RenderOptions::create()
    ->setPageSize('A4')
    ->setLandscape(false)
    ->setDisplayHeaderFooter(true)
    ->setFooterTemplate('
        <div style="font-size: 8px; text-align: center; width: 100%; color: #888;">
            Page <span class="pageNumber"></span>
        </div>
    ');

PdfMerger::create()
    ->addHtml('<h1>Cover</h1>', options: $coverOptions)
    ->addFile('/templates/chapter-1.html', options: $chapterOptions)
    ->addFile('/templates/chapter-2.html', options: $chapterOptions)
    ->save('/reports/merged.pdf');

Внедрение CSS

Класс StyleInjector подставляет CSS-правила перед отрендеренной страницей. Это полезно для применения глобальной брендовой таблицы стилей к шаблонам, которые вы не контролируете.

php
use Yeeefang\TcpdfNext\Artisan\HtmlRenderer;
use Yeeefang\TcpdfNext\Artisan\StyleInjector;

$injector = StyleInjector::create()
    ->addCss('
        body {
            font-family: "Inter", "Noto Sans TC", sans-serif;
            font-size: 11pt;
            line-height: 1.6;
            color: #333;
        }
        h1 { color: #1a237e; }
    ')
    ->addCssFile('/styles/brand.css');

HtmlRenderer::create()
    ->loadFile('/templates/report.html')
    ->withStyleInjector($injector)
    ->save('/output/branded-report.pdf');

Множественные слои стилей

Стили внедряются в порядке добавления. Более поздние правила переопределяют более ранние, следуя стандартной специфичности CSS.

php
$injector = StyleInjector::create()
    ->addCssFile('/styles/reset.css')
    ->addCssFile('/styles/brand.css')
    ->addCss('table { page-break-inside: avoid; }');  // overrides

Скриншоты

Класс ScreenshotCapture рендерит HTML в форматы изображений вместо PDF. Полезно для генерации миниатюр, превью для социальных сетей или визуального регрессионного тестирования.

php
use Yeeefang\TcpdfNext\Artisan\ScreenshotCapture;

// Full page screenshot as PNG
ScreenshotCapture::create()
    ->loadHtml('<h1>Preview</h1><p>This will be a PNG image.</p>')
    ->fullPage(true)
    ->format('png')
    ->save('/output/preview.png');

JPEG с настройкой качества

php
ScreenshotCapture::create()
    ->loadUrl('https://example.com/dashboard')
    ->format('jpeg')
    ->quality(85)
    ->save('/output/dashboard.jpg');

Настройка вьюпорта

php
ScreenshotCapture::create()
    ->loadFile('/templates/email.html')
    ->viewport(width: 1200, height: 800)
    ->deviceScaleFactor(2)  // retina
    ->fullPage(false)
    ->save('/output/email-preview.png');

Конфигурация Chrome

Пользовательский путь к бинарному файлу

Artisan автоматически обнаруживает Chrome по стандартным путям ОС. Переопределите с помощью chromePath.

php
use Yeeefang\TcpdfNext\Artisan\HtmlRenderer;

$renderer = HtmlRenderer::create(
    chromePath: '/opt/google/chrome/chrome',
);

Или установите переменную окружения CHROME_PATH глобально.

Флаги headless-режима

Artisan передаёт --headless=new по умолчанию (Chrome 112+). Вы можете добавить дополнительные флаги для специфических окружений.

php
$renderer = HtmlRenderer::create(
    chromeFlags: [
        '--no-sandbox',            // required in Docker
        '--disable-gpu',           // recommended in Docker
        '--disable-dev-shm-usage', // avoid /dev/shm issues
        '--font-render-hinting=none',
    ],
);

Пул соединений

Для сценариев высокой пропускной способности повторно используйте один экземпляр Chrome для нескольких рендеров. Это устраняет стоимость запуска (приблизительно 300--500 мс) для каждого последующего рендера.

php
use Yeeefang\TcpdfNext\Artisan\ChromeBridge;
use Yeeefang\TcpdfNext\Artisan\HtmlRenderer;

// Create a persistent bridge
$bridge = ChromeBridge::create(chromePath: '/usr/bin/chromium');

// Reuse across multiple renders
foreach ($reports as $report) {
    HtmlRenderer::createWithBridge($bridge)
        ->loadHtml($report->html)
        ->save("/output/{$report->id}.pdf");
}

// Explicitly close when done
$bridge->close();

Обработка ошибок

Все исключения Artisan наследуют Yeeefang\TcpdfNext\Artisan\Exceptions\ArtisanException.

php
use Yeeefang\TcpdfNext\Artisan\Exceptions\RenderException;
use Yeeefang\TcpdfNext\Artisan\Exceptions\ChromeNotFoundException;
use Yeeefang\TcpdfNext\Artisan\Exceptions\TimeoutException;

try {
    HtmlRenderer::create()->loadUrl($url)->save($path);
} catch (ChromeNotFoundException $e) {
    // Install Chrome or set CHROME_PATH
} catch (TimeoutException $e) {
    // Increase timeout or check network
} catch (RenderException $e) {
    // Inspect $e->getMessage() for details
}
ИсключениеТипичная причина
ChromeNotFoundExceptionChrome не установлен, CHROME_PATH некорректен
TimeoutExceptionМедленная страница, неразрешённые JS-промисы, сетевые проблемы
RenderExceptionНевалидный HTML, падение Chrome, ошибка записи на диск

Советы по производительности

  1. Повторно используйте экземпляры Chrome -- Используйте ChromeBridge для пакетных операций.
  2. Минимизируйте JavaScript -- Чем меньше JS Chrome должен выполнить, тем быстрее рендеринг.
  3. Встраивайте критический CSS -- Избегайте загрузки внешних таблиц стилей, когда возможно.
  4. Устанавливайте жёсткий таймаут -- Быстро завершайте на сломанных страницах, а не блокируйте очередь.
  5. Используйте setPrintBackground(false) -- Пропускайте рендеринг фона, когда он не нужен.

Далее

  • Render Options -- Размер страницы, поля и шаблоны колонтитулов.
  • Настройка Docker -- Запуск Artisan в контейнеризованных окружениях.
  • Обзор -- Краткое описание пакета и установка.

Распространяется по лицензии LGPL-3.0-or-later.