Il modello a pipeline
Spec: ISO 32000-2, §7.5 ISO 32000-2 §7.5 Evidence: Code-backed
In sintesi
Sezione intitolata “In sintesi”Un documento NextPDF non viene prodotto in un unico passaggio opaco. Passa attraverso poche fasi esplicite: una facciata che registra l’intento, un livello di contenuto che trasforma l’intento in un modello e un writer che serializza quel modello in un PDF conforme. Questa pagina descrive tale struttura e le ragioni di questa scelta.
Perché è importante
Sezione intitolata “Perché è importante”Il formato PDF è di per sé una struttura a strati — un’intestazione, un corpo di oggetti, una tabella di riferimenti incrociati e un trailer — e un writer deve assemblare il tutto in modo coerente. Se il motore che lo genera è una procedura unica e aggrovigliata, ogni modifica mette a rischio ogni output. L’unico modo per acquisire fiducia diventa allora eseguire il rendering di documenti interi e ispezionarli a occhio, un metodo lento, tardivo e poco convincente.
Una pipeline esplicita ribalta questa situazione. Ogni fase ha un solo compito e un confine tipizzato; così è possibile ragionare su una modifica e testarla nella fase interessata, non soltanto al termine del file. L’architettura è innanzitutto una scelta di testabilità ed estensibilità.
La versione breve
Sezione intitolata “La versione breve”- Il punto di ingresso pubblico è una facciata Document. È un costruttore fluente, a uso singolo e sicuro per i worker, che registra ciò che si vuole ottenere, non come viene serializzato.
- La facciata delega a circa due dozzine di trait di competenza focalizzati (output di testo, disegno, pagine, sicurezza, navigazione e così via) — ognuno con una sola responsabilità, invece di un’unica classe gigante.
- Il contenuto arriva tramite uno dei due percorsi: disegno diretto (primitive grafiche) o il motore HTML/CSS. Entrambi producono lo stesso modello di documento interno.
- Un writer PDF dedicato serializza quel modello, scegliendo una strategia PDF 1.4 / 1.7 / 2.0. La produzione di una struttura di file valida vive qui e in nessun altro luogo.
- Lo stato di lunga durata (i registri dei font e delle immagini) ha ambito di processo ed è condiviso; lo stato per richiesta (il documento) viene creato da zero e mai riutilizzato. Il confine è esplicito, ed è ciò che rende sicuri i runtime worker.
Come NextPDF lo affronta
Sezione intitolata “Come NextPDF lo affronta”Il modo più chiaro per vedere il modello è seguire un documento dalla chiamata ai byte.
- 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.
Due scelte di progettazione rendono tutto questo più di un diagramma.
La facciata è composta, non monolitica. Document non implementa ogni funzionalità in proprio; delega ogni ambito a un trait di competenza dedicato — output di testo, disegno, pagine, sicurezza, tipografia, navigazione, transazioni e così via. Un nuovo metodo del documento ricade nel trait responsabile del relativo ambito, non nella facciata stessa. La classe chiamata dal codice resta piccola e le responsabilità restano separate.
Il writer ha la responsabilità esclusiva della struttura del file. La produzione del contenuto decide quali segni e oggetti esistono; il writer decide come diventano un file PDF valido, inclusa la strategia di versione applicabile. Questa separazione è imposta come regola architetturale: il codice di layout e contenuto non emette la struttura finale del file e il writer non prende decisioni di layout. Il vantaggio è che «l’output è un PDF valido?» ha un unico luogo in cui essere testato.
Il confine della durata dello stato fa parte del modello, non è un ripensamento. I registri dei font e delle immagini vivono per l’intera durata del processo e sono condivisi tra le richieste; il documento, il suo contesto di rendering e il writer vengono creati per ogni richiesta e poi scartati. In un runtime worker, questa distinzione è la differenza tra riutilizzo sicuro e corruzione tra richieste. Per questo motivo è dichiarata nell’architettura, non affidata alla sola disciplina.
Cosa dicono le prove
Sezione intitolata “Cosa dicono le prove”Questa pagina è Evidence: Code-backed . Le fasi corrispondono a una struttura reale nel repository core:
- La facciata e la sua delega sono
src/Core/Document.phpe i trait di competenza insrc/Core/Concerns/(output di testo, output, disegno, pagine, sicurezza, tipografia, navigazione, transazioni e altro ancora — ciascuno con una singola responsabilità). - I due percorsi di contenuto sono il motore HTML/CSS (
src/Html/) e il disegno diretto (src/Graphics/), entrambi alimentano il modello interno. - La serializzazione e la strategia di versione PDF vivono in
src/Writer/(PdfWriter.php, con classi di strategia PDF 1.4 / 1.7 / 2.0 esplicite). - Il confine tra durata di processo e durata per richiesta è la progettazione sicura per i worker registrata nella panoramica dell’architettura ed esercitata dall’esempio fornito di worker-factory, che condivide un
FontRegistrye unImageRegistrytra le richieste, creando da zero ogniDocument.
Il risultato è vincolato dal formato. L’output del writer deve essere un’intestazione, un corpo di oggetti, una tabella di riferimenti incrociati e un trailer secondo Spec: ISO 32000-2, §7.5 ISO 32000-2 §7.5 . Concentrare tale obbligo in un’unica fase è ciò che permette al resto del motore di concentrarsi sul contenuto invece che sull’assemblaggio della struttura del file.
Esempio pratico
Sezione intitolata “Esempio pratico”Il compito della facciata è rendere leggibile l’intento come tale. Il percorso del contenuto e il writer restano invisibili nel punto di chiamata:
<?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 stageOgni chiamata ricade in una competenza diversa. Due percorsi di contenuto diversi alimentano lo stesso modello. Esattamente una fase — save() — trasforma il modello in byte di file. Il punto di chiamata non deve sapere come viene costruita la tabella di riferimenti incrociati.
Equivoco comune
Sezione intitolata “Equivoco comune”Il fraintendimento più frequente è che «pipeline» implichi un’API push in streaming da collegare fase per fase, come una pipe Unix. Non è così. Qui la pipeline è una decomposizione architetturale: fasi con responsabilità singole e confini tipizzati. Si continua comunque a programmare tramite una facciata fluente. Le fasi sono il modo in cui il motore viene costruito e testato, non un meccanismo di trasporto da assemblare a mano.
Un errore affine è presumere che la facciata sia il motore. È il punto di ingresso. Il lavoro effettivo è distribuito tra i trait di competenza, i due percorsi di contenuto e un writer. Questa distribuzione è precisamente il motivo per cui la modifica di una funzionalità non mette a rischio ogni output.
Limiti e confini
Sezione intitolata “Limiti e confini”Questa pagina descrive la forma della pipeline, non l’API interna di una singola fase. L’inventario esatto dei trait di competenza, le regole di selezione della strategia del writer e i campi del modello di contenuto sono definiti dal codice e dalla reference, non da questa spiegazione. Il conteggio preciso dei trait è un dettaglio implementativo che può cambiare senza cambiare il modello. Questa pagina non copre le fasi interne del motore HTML (un argomento a parte) né il comportamento di streaming e memoria del writer (anch’esso a parte). Le affermazioni strutturali sono accurate alla data di revisione di questa pagina; le fonti autorevoli sono src/Core/, src/Html/, src/Graphics/ e src/Writer/ del repository core.
Il modello a pipeline è identico in tutte le edizioni; le edizioni aggiungono capacità all’interno delle fasi, non nuove fasi:
| Edition | Availability |
|---|---|
| Core | Core implementa la pipeline completa facciata → contenuto → writer. |
| Pro | Pro aggiunge capacità all’interno delle fasi esistenti, non nuove fasi. |
| Enterprise | Enterprise aggiunge capacità all’interno delle fasi esistenti, non nuove fasi. |
Documenti correlati
Sezione intitolata “Documenti correlati”- Memoria e streaming — come la fase del writer mantiene la memoria limitata.
- La pipeline HTML — le fasi interne del percorso di contenuto HTML.
- Tipi rigorosi, ovunque — i confini tipizzati che rendono ogni fase testabile in modo indipendente.
Glossario
Sezione intitolata “Glossario”- Facciata — il punto di ingresso pubblico
Document: un costruttore fluente e a uso singolo che registra l’intento e delega ai trait di competenza. - Trait di competenza — un trait PHP focalizzato che la facciata compone, ciascuno responsabile di una singola area di funzionalità (output di testo, disegno, pagine, sicurezza e così via).
- Percorso di contenuto — uno dei due modi in cui il contenuto entra nel modello: disegno diretto o il motore HTML/CSS.
- Modello di documento — lo stato interno e tipizzato del motore, in cui si accumulano pagine, contenuto e risorse prima della serializzazione.
- Fase del writer — il componente che serializza il modello in un PDF valido, selezionando una strategia PDF 1.4 / 1.7 / 2.0.
- Sicuro per i worker — progettato in modo che lo stato di durata di processo sia condiviso in sicurezza, mentre lo stato per richiesta viene creato da zero e mai riutilizzato.