Le modèle de pipeline
Spec: ISO 32000-2, §7.5 ISO 32000-2 §7.5 Evidence: Code-backed
Un document NextPDF n’est pas produit par une unique étape opaque. Il passe par un petit nombre d’étapes explicites : une façade qui enregistre l’intention, une couche de contenu qui transforme cette intention en modèle, puis un writer qui sérialise ce modèle en un PDF conforme. Cette page explique cette structure et les raisons de ce choix.
Pourquoi c’est important
Section intitulée « Pourquoi c’est important »Le format de fichier PDF est lui-même structuré en couches — un en-tête, un corps d’objets, une table de références croisées et une bande-annonce — et un writer doit assembler le tout de manière cohérente. Si le moteur qui le produit se réduit à une procédure unique et enchevêtrée, chaque modification met en péril toutes les sorties. Le seul moyen de gagner en confiance consiste alors à générer des documents entiers et à les inspecter à l’œil, ce qui est lent, tardif et peu convaincant.
Un pipeline explicite inverse la situation. Chaque étape a une seule tâche et une frontière typée, de sorte que tu peux raisonner sur une modification et la tester au niveau de l’étape concernée, pas seulement à la fin du fichier. L’architecture est avant tout un choix de testabilité et d’extensibilité.
La version courte
Section intitulée « La version courte »- Le point d’entrée public est une façade Document. C’est un constructeur fluide, à usage unique et sûr pour les workers, qui enregistre ce que tu veux, et non la manière dont c’est sérialisé.
- La façade délègue à une vingtaine de traits de responsabilité ciblés (sortie de texte, dessin, pages, sécurité, navigation, etc.) — chacun avec une seule responsabilité, plutôt qu’une seule classe géante.
- Le contenu arrive par l’un des deux chemins : le dessin direct (primitives graphiques) ou le moteur HTML/CSS. Les deux produisent le même modèle de document interne.
- Un writer PDF dédié sérialise ce modèle en choisissant une stratégie PDF 1.4 / 1.7 / 2.0. La production d’une structure de fichier valide se fait ici, et nulle part ailleurs.
- L’état de longue durée (les registres de polices et d’images) est limité au processus et partagé ; l’état propre à chaque requête (le document) est créé à neuf et jamais réutilisé. La frontière est explicite, et c’est ce qui rend les environnements d’exécution de workers sûrs.
L’approche de NextPDF
Section intitulée « L’approche de NextPDF »Le moyen le plus clair de voir le modèle est de suivre un document depuis l’appel jusqu’aux octets.
- Document facade Fluent, use-once builder ; records intent via concern traits.
- Content production Direct drawing or the HTML/CSS engine — both build one document model.
- Document model Accumulated pages, content, and resources held as typed state.
- PDF writer Serialises the model ; selects a PDF 1.4 / 1.7 / 2.0 strategy.
- Conforming PDF Header, object body, cross-reference table, trailer.
Deux choix de conception en font plus qu’un simple schéma.
La façade est composée, pas monolithique. Document n’implémente pas lui-même chaque fonctionnalité ; il délègue chaque domaine à un trait de responsabilité dédié — sortie de texte, dessin, pages, sécurité, typographie, navigation, transactions, etc. Toute nouvelle méthode de document a sa place dans le trait responsable de son domaine, pas sur la façade elle-même. La classe que tu appelles reste compacte, et les responsabilités restent séparées.
Le writer est seul responsable de la structure de fichier. La production de contenu décide quels tracés et objets existent ; le writer décide comment ils deviennent un fichier PDF valide, y compris la stratégie de version à appliquer. Cette séparation est imposée comme règle architecturale : le code de mise en page et de contenu n’émet pas la structure de fichier finale, et le writer ne prend pas de décisions de mise en page. L’avantage, c’est que « la sortie est-elle un PDF valide ? » a un seul et unique endroit où être testée.
La frontière de durée de vie fait partie du modèle ; ce n’est pas un ajout tardif. Les registres de polices et d’images vivent pendant toute la durée du processus et sont partagés entre les requêtes ; le document, son contexte de rendu et le writer sont créés pour chaque requête puis libérés. Dans un environnement d’exécution de workers, cette distinction fait toute la différence entre une réutilisation sûre et une corruption entre requêtes. C’est pourquoi elle est formalisée dans l’architecture, et non laissée à la seule discipline.
Ce que dit la preuve
Section intitulée « Ce que dit la preuve »Cette page est Evidence: Code-backed . Les étapes correspondent à une structure réelle dans le dépôt principal :
- La façade et sa délégation se trouvent dans
src/Core/Document.php, avec les traits de responsabilité danssrc/Core/Concerns/(sortie de texte, sortie, dessin, pages, sécurité, typographie, navigation, transactions, entre autres — chacun avec une seule responsabilité). - Les deux chemins de contenu sont le moteur HTML/CSS (
src/Html/) et le dessin direct (src/Graphics/), tous deux alimentant le modèle interne. - La sérialisation et la stratégie de version PDF résident dans
src/Writer/(PdfWriter.php, avec des classes explicites de stratégie PDF 1.4 / 1.7 / 2.0). - La frontière entre la durée de vie du processus et la portée par requête est le modèle sûr pour les workers décrit dans l’aperçu de l’architecture et mis en œuvre dans l’exemple fourni de fabrique de workers, qui partage un
FontRegistryet unImageRegistryentre les requêtes tout en créant chaqueDocumentà neuf.
Le format fixe le résultat attendu. La sortie du writer doit être un en-tête, un corps d’objets, une table de références croisées et une bande-annonce, conformément à Spec: ISO 32000-2, §7.5 ISO 32000-2 §7.5 . Concentrer cette obligation dans une seule étape permet au reste du moteur de rester concentré sur le contenu plutôt que sur l’assemblage de la structure de fichier.
Exemple pratique
Section intitulée « Exemple pratique »Le rôle de la façade est de faire en sorte que l’intention reste lisible comme telle. Le chemin de contenu et le writer restent invisibles au point d’appel :
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone(); // facade$doc->setTitle('Quarterly Report'); // metadata concern$doc->addPage(); // pages concern$doc->setFont('helvetica', 'B', 16); // typography concern$doc->cell(0, 12, 'Summary', newLine: true); // text-output concern$doc->writeHtml('<p>Generated in-process.</p>'); // HTML content path$doc->save(__DIR__ . '/report.pdf'); // writer stageChaque appel aboutit dans une responsabilité différente. Deux chemins de contenu différents alimentent le même modèle. Une seule étape — save() — transforme le modèle en octets de fichier. Rien au point d’appel n’a besoin de savoir comment la table de références croisées est construite.
Idée fausse courante
Section intitulée « Idée fausse courante »Une interprétation fréquente consiste à croire qu’un « pipeline » implique une API push de flux que tu branches étape par étape, comme un pipe Unix. Ce n’est pas le cas. Le pipeline est ici une décomposition architecturale : des étapes avec des responsabilités uniques et des frontières typées. Tu continues d’utiliser une façade fluide. Les étapes décrivent la façon dont le moteur est construit et testé, pas un transport que tu assembles à la main.
Une erreur connexe consiste à supposer que la façade est le moteur. Elle n’est que le point d’entrée. Le vrai travail est réparti entre les traits de responsabilité, deux chemins de contenu et un writer. C’est précisément cette répartition qui évite qu’une modification d’une fonctionnalité mette en péril toutes les sorties.
Limites et frontières
Section intitulée « Limites et frontières »Cette page décrit la structure du pipeline, pas l’API interne d’une étape donnée. L’inventaire exact des traits de responsabilité, les règles de sélection de la stratégie du writer et les champs du modèle de contenu sont définis par le code et la référence, pas par cette explication. Le nombre précis de traits est un détail d’implémentation qui peut changer sans modifier le modèle. Cette page ne couvre pas les étapes internes du moteur HTML (un sujet distinct) ni le comportement de flux et de mémoire du writer (également distinct). Les affirmations structurelles sont exactes à la date de révision de cette page ; la source faisant autorité est src/Core/, src/Html/, src/Graphics/ et src/Writer/ du dépôt principal.
Le modèle de pipeline est identique d’une édition à l’autre ; les éditions ajoutent des capacités au sein des étapes, pas de nouvelles étapes :
| Edition | Availability |
|---|---|
| Core | Core implémente le pipeline complet façade → contenu → writer. |
| Pro | Pro ajoute des capacités au sein des étapes existantes, pas de nouvelles étapes. |
| Enterprise | Enterprise ajoute des capacités au sein des étapes existantes, pas de nouvelles étapes. |
Documents associés
Section intitulée « Documents associés »- Mémoire et flux — comment l’étape du writer borne la mémoire.
- Le pipeline HTML — les étapes internes du chemin de contenu HTML.
- Le typage strict, partout — les frontières typées qui rendent chaque étape testable indépendamment.
Glossaire
Section intitulée « Glossaire »- Façade — le point d’entrée public
Document: un constructeur fluide, à usage unique, qui enregistre l’intention et délègue aux traits de responsabilité. - Trait de responsabilité — un trait PHP ciblé composé par la façade, responsable d’un seul domaine fonctionnel (sortie de texte, dessin, pages, sécurité, etc.).
- Chemin de contenu — l’une des deux façons dont le contenu entre dans le modèle : le dessin direct ou le moteur HTML/CSS.
- Modèle de document — l’état interne typé dans lequel le moteur accumule les pages, le contenu et les ressources avant la sérialisation.
- Étape du writer — le composant qui sérialise le modèle en un PDF valide en sélectionnant une stratégie PDF 1.4 / 1.7 / 2.0.
- Sûr pour les workers — conçu pour que l’état dont la durée de vie suit le processus soit partagé en toute sécurité, tandis que l’état propre à chaque requête est créé à neuf et jamais réutilisé.