Skip to content

Fonctionnalités avancées

Au-delà du rendu HTML vers PDF basique, le package Artisan fournit des utilitaires pour fusionner des documents, injecter des styles globaux, capturer des captures d'écran et affiner le comportement de Chrome.

Fusion PDF

La classe PdfMerger combine plusieurs sources HTML en un seul document PDF. Chaque source est rendue comme une section séparée, et les résultats sont concaténés dans l'ordre.

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

$merger = PdfMerger::create();

$merger
    ->addHtml('<h1>Page de couverture</h1><p>Rapport annuel 2026</p>')
    ->addFile('/templates/chapitre-1.html')
    ->addFile('/templates/chapitre-2.html')
    ->addUrl('https://charts.example.com/resume-annuel')
    ->addHtml('<h1>Annexe</h1><p>Tableaux de données de support.</p>');

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

Options par section

Chaque section peut avoir ses propres RenderOptions. Par exemple, une page de couverture en paysage et des chapitres en portrait.

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>Couverture</h1>', options: $coverOptions)
    ->addFile('/templates/chapitre-1.html', options: $chapterOptions)
    ->addFile('/templates/chapitre-2.html', options: $chapterOptions)
    ->save('/reports/fusionné.pdf');

Injection CSS

La classe StyleInjector préfixe les règles CSS à la page rendue. Utile pour appliquer une feuille de style de marque globale aux templates que vous ne contrôlez pas.

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/marque.css');

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

Couches de style multiples

Les styles sont injectés dans l'ordre d'ajout. Les règles ultérieures surchargent les précédentes, suivant la spécificité CSS standard.

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

Captures d'écran

La classe ScreenshotCapture rend HTML vers formats image au lieu de PDF. Utile pour générer des miniatures, aperçus médias sociaux ou tests de régression visuelle.

php
use Yeeefang\TcpdfNext\Artisan\ScreenshotCapture;

// Capture d'écran pleine page en PNG
ScreenshotCapture::create()
    ->loadHtml('<h1>Aperçu</h1><p>Ceci sera une image PNG.</p>')
    ->fullPage(true)
    ->format('png')
    ->save('/output/aperçu.png');

JPEG avec qualité

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

Configuration viewport

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

Configuration Chrome

Chemin binaire personnalisé

Artisan auto-détecte Chrome sur les chemins OS courants. Surcharger avec chromePath.

php
use Yeeefang\TcpdfNext\Artisan\HtmlRenderer;

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

Ou définir la variable d'environnement CHROME_PATH globalement.

Drapeaux mode headless

Artisan passe --headless=new par défaut (Chrome 112+). Vous pouvez ajouter des drapeaux supplémentaires pour environnements spécifiques.

php
$renderer = HtmlRenderer::create(
    chromeFlags: [
        '--no-sandbox',            // requis dans Docker
        '--disable-gpu',           // recommandé dans Docker
        '--disable-dev-shm-usage', // éviter problèmes /dev/shm
        '--font-render-hinting=none',
    ],
);

Pooling de connexions

Pour scénarios haut débit, réutilisez une instance Chrome unique à travers plusieurs rendus. Cela élimine le coût de démarrage (environ 300-500 ms) pour chaque rendu suivant.

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

// Créer un bridge persistant
$bridge = ChromeBridge::create(chromePath: '/usr/bin/chromium');

// Réutiliser à travers plusieurs rendus
foreach ($reports as $report) {
    HtmlRenderer::createWithBridge($bridge)
        ->loadHtml($report->html)
        ->save("/output/{$report->id}.pdf");
}

// Fermer explicitement quand terminé
$bridge->close();

Gestion des erreurs

Toutes les exceptions Artisan étendent 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) {
    // Installer Chrome ou définir CHROME_PATH
} catch (TimeoutException $e) {
    // Augmenter timeout ou vérifier réseau
} catch (RenderException $e) {
    // Inspecter $e->getMessage() pour détails
}
ExceptionCause courante
ChromeNotFoundExceptionChrome non installé, CHROME_PATH incorrect
TimeoutExceptionPage lente, promesses JS non résolues, problèmes réseau
RenderExceptionHTML invalide, crash Chrome, échec écriture disque

Conseils de performance

  1. Réutiliser instances Chrome -- Utiliser ChromeBridge pour opérations par lots.
  2. Minimiser JavaScript -- Moins Chrome doit exécuter de JS, plus rapide le rendu.
  3. Inline CSS critique -- Éviter récupérations de feuilles de style externes quand possible.
  4. Définir timeout serré -- Échouer rapidement sur pages cassées plutôt que bloquer la file.
  5. Utiliser setPrintBackground(false) -- Sauter rendu arrière-plan quand vous n'en avez pas besoin.

Prochaines étapes

Distribué sous licence LGPL-3.0-or-later.