Salta ai contenuti
getnextpdf.com

Migrazione da FPDF a NextPDF

Questa guida aiuta a spostare un codebase basato su FPDF verso il core di NextPDF. FPDF è una delle librerie Portable Document Format (PDF) PHP legacy più ampiamente diffuse, e la sua superficie di disegno — AddPage, SetFont, Cell, MultiCell, Write, Text, Image, Output pilotata da un cursore x/y manuale — si mappa in modo pulito sulla stessa API cell/text di NextPDF, perché i metodi di disegno di basso livello di NextPDF seguono la stessa discendenza FPDF/TCPDF. NextPDF non è però un clone drop-in di FPDF: è un motore PDF 2.0 moderno con tipi rigorosi, subsetting dei font, firma, PDF/A e accessibilità (tagged PDF). I due veri spostamenti sono il modello di unità (NextPDF lavora in punti PDF; FPDF usa di default i millimetri) e i verbi di output (un’enum OutputDestination tipizzata anziché i caratteri 'I'/'D'/'F'/'S' di FPDF).

Non esiste alcuno shim della classe FPDF in core. Riscrivere ogni call site usando la mappatura dei verbi. Se si desidera la modifica iniziale più piccola per un codebase TCPDF 6.x, vedere invece l’adattatore di compatibilità TCPDF, che include un percorso drop-in quasi compatibile con il sorgente; FPDF non ha un tale adattatore.

Terminal window
composer require nextpdf/core:^3

Mantenere setasign/fpdf (o il proprio fpdf/fpdf) installato durante la migrazione. Rimuoverlo dopo il passaggio finale (vedere sequenza di migrazione sicura).

FPDF e NextPDF condividono lo stesso modello mentale: un documento fatto di pagine, un cursore (la posizione x/y corrente) e verbi che disegnano alla posizione del cursore o la fanno avanzare. SetXY, Cell, Ln e MultiCell leggono e mutano tutti il cursore in entrambe le librerie, quindi la maggior parte del codice procedurale FPDF si traduce riga per riga.

Le differenze sono deliberate, non accidentali:

  • Unità. Il costruttore di FPDF (new FPDF($orientation, $unit, $size)) usa di default i millimetri. NextPDF lavora in punti PDF (1 pt = 1/72 in, ISO 32000-2 §7). Non esiste alcuna manopola di unità a livello di documento — convertire i mm in punti una volta (pt = mm * 72 / 25.4).
  • La direzione Y resta la stessa per voi. Come FPDF, le coordinate utente di NextPDF mettono y = 0 in cima alla pagina e aumentano verso il basso, quindi l’aritmetica del cursore porta direttamente. NextPDF converte internamente all’origine PDF-nativa in basso a sinistra.
  • La costruzione è esplicita. FPDF accorpa orientamento, unità e dimensione nel costruttore; NextPDF accetta un value object immutabile NextPDF\Core\Config (dimensione della pagina, margini, directory dei font) e un addPage() esplicito.
  • Sempre Unicode, sempre subset. La build core di FPDF è Latin-1 e necessita della variante tFPDF/UTF-8 per Unicode. NextPDF è UTF-8 ovunque e incorpora sempre i font come programmi subset (ISO 32000-2 §9). I file AddFont/metriche-font di FPDF non hanno alcun analogo; registrare una directory di font TrueType/OpenType e selezionare la famiglia per nome.

I principali punti di ingresso usati di seguito sono Document::createStandalone(), Document::addPage(), Document::setFont(), Document::cell(), Document::multiCell(), Document::text(), Document::write(), Document::ln(), Document::image(), gli accessor del cursore (setXY/setX/ setY/getX/getY), Document::output(?string, OutputDestination), Document::save(string $path): void, Document::getPdfData(): string e il value object NextPDF\Core\Config. Il riferimento completo per questi metodi core di disegno, testo e output vive nei moduli core e nell’indice del riferimento, auto-generato dal PHPDoc. Il modulo Html è lettura correlata per HTML-in-PDF, non il riferimento per i verbi di questa pagina.

I nomi dei metodi pubblici di FPDF sono di lunga data e ben noti. La colonna NextPDF qui sotto è confermata rispetto alle firme del codice sorgente core (vedere Evidenze / tracciabilità).

FPDFNextPDFNotes
new FPDF($orient, $unit, $size)Document::createStandalone($config)Gli argomenti orientamento/unità/dimensione del costruttore diventano un NextPDF\Core\Config (pageSize, margins, fontsDirectory). Nessun $unit — lavorare in punti. La pagina predefinita di createStandalone() è A4 verticale.
$pdf->AddPage($orient, $size)$doc->addPage($size, $orientation)Mappatura diretta. $size è un value object PageSize; $orientation è l’enum Orientation (Portrait/Landscape).
$pdf->SetFont($family, $style, $size)$doc->setFont($family, $style, $size)Mappatura diretta. $style usa gli stessi codici ''/'B'/'I'/'BI' (più 'U' per la sottolineatura).
$pdf->Cell($w, $h, $txt, $border, $ln, $align, $fill)$doc->cell($w, $h, $txt, $border, $newLine, $align, $fill)Mappatura diretta. $align è l’enum Alignment (Left/Center/Right/Justify); $border accetta bool o una stringa 'LTRB'; $ln diventa il bool $newLine.
$pdf->MultiCell($w, $h, $txt, $border, $align, $fill)$doc->multiCell($w, $h, $txt, $border, $align)Va a capo sulle metriche reali del font. Nessun argomento $fill; disegnare prima un rect() riempito se serve uno sfondo.
$pdf->Write($h, $txt, $link)$doc->write($h, $txt, $link)Testo a flusso dal cursore; $link allega un’annotazione di link URL.
$pdf->Text($x, $y, $txt)$doc->text($x, $y, $txt)Testo a posizione assoluta. Mappatura diretta.
$pdf->Ln($h)$doc->ln($h)A capo al margine sinistro; 0 = altezza di riga predefinita.
$pdf->Image($file, $x, $y, $w, $h)$doc->image($file, $x, $y, $w, $h)Mappatura diretta; $x/$y/$w/$h sono nullable (null = cursore corrente / dimensione intrinseca).
$pdf->SetXY($x, $y) / SetX / SetY$doc->setXY($x, $y) / setX / setYMappatura diretta. getX()/getY() leggono il cursore.
$pdf->SetMargins($l, $t, $r)$doc->setMargins(new Margin($t, $r, $bottom, $l))Un value object Margin; l’ordine del costruttore è (top, right, bottom, left)non quello di FPDF (left, top, right). SetMargins di FPDF non ha argomento bottom (il suo margine inferiore proviene da SetAutoPageBreak($auto, $margin)), quindi scegliere $bottom da soli — comunemente uguale al margine superiore, o passare il margine di auto-page-break.
$pdf->SetAutoPageBreak($auto, $margin)$doc->setAutoPageBreak($auto, $margin)Mappatura diretta.
$pdf->SetDrawColor / SetFillColor / SetTextColor$doc->setDrawColor / setFillColor / setTextColorRGB (r, g, b), o un singolo valore per la scala di grigi.
$pdf->Line / Rect / SetLineWidth$doc->line / rect / setLineWidthMappatura diretta. rect() accetta una stringa di stile ('S'/'F'/'DF').
$pdf->SetTitle/SetAuthor/SetSubject/SetKeywords/SetCreator$doc->setTitle/setAuthor/setSubject/setKeywords/setCreatorMappatura diretta. Finisce nel dizionario informativo / Extensible Metadata Platform (XMP) §14 di ISO 32000-2.
$pdf->Output($dest, $name)$doc->output($name, OutputDestination::…)I caratteri di destinazione di FPDF (I/D/F/S) si mappano sull’enum OutputDestination; notare che l’ordine degli argomenti si scambia (nome per primo in NextPDF).
$pdf->Output('S')$doc->getPdfData()Restituisce i byte del PDF.
$pdf->Output('F', $path)$doc->save($path)Scrive su un percorso di file.
$pdf->GetStringWidth($s)(no public method)La larghezza della stringa è calcolata internamente durante il word-wrap di cell()/multiCell(); non c’è alcun verbo pubblico di misurazione per stringa. Pilotare il word-wrap tramite multiCell() anziché misurare a mano.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Contracts\Alignment;
use NextPDF\Core\Document;
// FPDF:
// $pdf = new FPDF(); // mm, A4 portrait
// $pdf->AddPage();
// $pdf->SetFont('Arial', 'B', 16);
// $pdf->Cell(40, 10, 'Invoice');
// $pdf->Output('F', 'out.pdf');
// NextPDF — points, default page is A4 portrait:
$doc = Document::createStandalone();
$doc->setTitle('Invoice');
$doc->addPage();
$doc->setFont('Helvetica', 'B', 16.0);
$doc->cell(113.4, 28.3, 'Invoice', false, true, Alignment::Left); // ~40mm x ~10mm in points
$doc->save(__DIR__ . '/out.pdf');
echo "Wrote out.pdf\n";

Questo esempio è allineato con examples/04-text-and-fonts.php. Usa una dimensione di pagina esplicita, margini, una directory di font registrata e il modello cell pilotato dal cursore che un codebase FPDF già usa.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Contracts\Alignment;
use NextPDF\Contracts\OutputDestination;
use NextPDF\Core\Config;
use NextPDF\Core\Document;
use NextPDF\ValueObjects\Margin;
use NextPDF\ValueObjects\PageSize;
// Equivalent of: new FPDF('P', 'mm', 'A4') + SetMargins(20, 16, 20)
// i.e. FPDF left=20mm, top=16mm, right=20mm. FPDF SetMargins has no bottom
// argument, so we pick bottom = top = 16mm. Convert each mm to points
// (pt = mm * 72 / 25.4): 16mm = 45.354pt, 20mm = 56.693pt.
// Margin constructor order is (top, right, bottom, left) — NOT FPDF's (L, T, R).
$config = new Config(
pageSize: new PageSize(595.276, 841.890, 'A4'),
margins: new Margin(45.354, 56.693, 45.354, 56.693), // top,right,bottom,left in points
fontsDirectory: __DIR__ . '/fonts',
);
$doc = Document::createStandalone($config);
$doc->setTitle('Quarterly Report');
$doc->setAuthor('Finance');
$doc->addPage();
// SetFont + Cell, the FPDF way — but in points and with a real Unicode font.
$doc->setFont('DejaVuSans', 'B', 18.0);
$doc->setTextColor(30, 58, 138);
$doc->cell(0, 24.0, 'Quarterly Report', false, true, Alignment::Left);
$doc->setFont('DejaVuSans', '', 11.0);
$doc->setTextColor(0, 0, 0);
$doc->multiCell(0, 16.0, "Body text wraps on real font metrics. Unicode is "
. "native, so accented and non-Latin characters need no tFPDF variant — "
. "register the family in the fonts directory and select it by name.");
// Equivalent of $pdf->Output('D', 'report.pdf'):
$doc->output('report.pdf', OutputDestination::Download);
  • Unità. Ogni coordinata numerica, larghezza, altezza e margine che si copia da FPDF è in millimetri per impostazione predefinita. Moltiplicare per 72 / 25.4 per ottenere i punti, una volta, durante il porting. Mescolare i due dimensiona-male tutto in modo silenzioso.
  • Ordine degli argomenti di Output(). FPDF è Output($dest, $name); NextPDF è output($name, $dest). La destinazione è l’enum OutputDestination, non un carattere. Preferire save() / getPdfData() per l’output su file / stringa.
  • Ordine di SetMargins. FPDF è (left, top, right); il value object Margin di NextPDF è (top, right, bottom, left). Riordinare, non trascrivere.
  • Font. I file AddFont() + .php di metriche di FPDF non hanno equivalente. Mettere il file TrueType/OpenType nella directory dei font e chiamare setFont() con il nome della famiglia. I nomi Base14 di Core (Helvetica, Times, Courier) si risolvono senza un file; sotto PDF/A o tagged PDF vengono auto-sostituiti con un font incorporabile.
  • GetStringWidth. Non esiste alcun metodo pubblico di misurazione delle stringhe. Se il proprio codice FPDF misura le stringhe per disporre le colonne a mano, convertire quel blocco a multiCell() (che va a capo sulle metriche) o a chiamate cell() a larghezza fissa.

NextPDF emette il contenuto in un singolo passaggio in streaming (architecture decision record ADR-001); la memoria di picco segue la dimensione del documento, non un albero di oggetti trattenuto. Il budget per l’esempio di questa guida è wall_ms: 2000, peak_mb: 128. Per documenti lunghi, pilotare il contenuto attraverso chiamate addPage() — la stessa forma di loop che un report FPDF già usa.

  • Metadati. SetTitle()/SetAuthor() si mappano su setter tipizzati che scrivono il dizionario informativo / XMP §14 di ISO 32000-2. Non memorizzare mai segreti lì.
  • Percorsi delle immagini. image() rifiuta gli schemi stream-wrapper e i byte NUL incorporati prima della lettura. Passare percorsi controllati dall’applicazione.
  • Nessun codice nel documento. NextPDF non esegue alcuno script nel documento; nulla in FPDF cambia questo.
StatementSpecClause
Formato/orientamento della pagina si mappano sul box di confine della pagina.ISO 32000-2§7
I font sono scritti come programmi di font incorporati/subset.ISO 32000-2§9
Titolo / metadati finiscono nel dizionario informativo / XMP.ISO 32000-2§14
Linee, rettangoli e immagini sono painting del content stream.ISO 32000-2§8

NextPDF produce contenuto ISO 32000-2; non afferma l’identità visiva con FPDF. Ri-revisionare l’output ogni volta che si cambia renderer.

Non applicabile. Il core di NextPDF copre il percorso di migrazione FPDF descritto qui.


Team che eseguono FPDF (o tFPDF) per la generazione PDF lato server, procedurale. Se il proprio codice è una sequenza di chiamate AddPage / SetFont / Cell / MultiCell / Image / Output pilotata da SetXY e Ln, la mappatura dei verbi copre l’intera superficie.

In ambito: i verbi di disegno di FPDF, il modello del cursore, i font, i colori, linee e rettangoli, i metadati e l’output. Fuori ambito: il tooling dei file di metriche AddFont di FPDF e le estensioni-script FPDF di terze parti (barcode, rotazione, segnalibri) — mappare quelle sui corrispondenti moduli NextPDF (Barcode, Transforms, Navigation), che non sono trattati qui.

Compatibilità comportamentale, non uno shim drop-in: core non fornisce alcuno shim della classe FPDF. Riscrivere ogni call site. I verbi si allineano da vicino perché l’API cell/text di NextPDF condivide la discendenza FPDF/TCPDF, ma il modello di unità, l’ordine degli argomenti di Output e i tipi Margin/enum differiscono — quindi una trascrizione è sbagliata, una traduzione è giusta.

FPDF constructNextPDFNotes
$unit ('mm' default)(no equivalent)Lavorare in punti PDF. Convertire le dimensioni con pt = mm * 72 / 25.4 una volta durante il porting.
$orientation ('P'/'L')Orientation enum on addPage(), or swap PageSize width/heightOrizzontale = larghezza > altezza.
$size ('A4', [w,h])Config->pageSize (PageSize value object)I formati con nome diventano dimensioni in punti esplicite; esistono le factory PageSize::A4()A0() e Letter/Legal.
SetMargins($l, $t, $r)Config->margins (Margin VO)Ordine del costruttore (top, right, bottom, left).
AddFont($family, $style, $file)fonts directory + setFont() by nameEliminare il file di metriche; mettere il TTF/OTF in Config->fontsDirectory.
  • Directory dei font. La registrazione per singolo font AddFont di FPDF collassa in una directory dei font più la corrispondenza della famiglia con setFont(). Iniziare con Config->fontsDirectory (il percorso di ricerca predefinito); registrare directory aggiuntive tramite FontRegistry::addFontDirectory() o Document::addFontDirectory() quando i font vivono in più di un posto.
  • Sempre Unicode. Nessun default Latin-1 e nessuna build tFPDF separata; l’input UTF-8 è la norma.
  • Sempre subset. NextPDF esegue sempre il subset dei font incorporati (ISO 32000-2 §9); le scelte di incorporamento dei font di FPDF non hanno equivalente e non sono necessarie.
  • Re-baseline dei glifi. La corrispondenza e il fallback dei font sono specifici del motore; un alias di font FPDF potrebbe necessitare di un nome di famiglia esatto. Le differenze di sostituzione sono attese, non difetti.
  • Conversione delle unità (mm → pt) — l’errore di porting più comune; vedere sopra.
  • L’ordine degli argomenti di Output si scambia e la destinazione diventa un’enum.
  • Margin / Alignment / Orientation sono oggetti/enum tipizzati, non caratteri o triple posizionali (l, t, r).
  • Nessun GetStringWidth pubblico — pilotare il word-wrap tramite multiCell().
  • Rasterizzazione indipendente — l’andata a capo e la paginazione su contenuto denso possono differire; ri-baseline dei diff visivi.

Queste sono differenze comportamentali documentate, non difetti in nessuno dei due motori.

  • Selettore $unit di FPDF — non modellato (sempre punti).
  • File di metriche AddFont() + .php/.z — sostituiti da una directory dei font.
  • GetStringWidth() — nessun verbo pubblico di misurazione delle stringhe.
  • I caratteri di destinazione 'I'/'D'/'F'/'S' di FPDF — sostituiti dall’enum OutputDestination + save()/getPdfData().

Il codice che dipende da questi non «migra» verbatim. Riesprimerlo con le righe sopra.

  1. Aggiungere nextpdf/core accanto a FPDF; mantenere FPDF installato per ora.
  2. Scegliere un documento a basso rischio. Convertire il costruttore tramite la mappa di unità, poi portare ogni verbo con la mappa dei verbi. Convertire ogni coordinata in mm in punti.
  3. Mettere i font del documento in Config->fontsDirectory e selezionarli per nome di famiglia; eliminare le chiamate AddFont.
  4. Generare entrambi i PDF per lo stesso input e confrontarli visivamente. Le differenze (sostituzione font, andata a capo) sono attese per motori indipendenti — accettarle per documento.
  5. Sostituire qualsiasi layout-a-mano basato su GetStringWidth con multiCell() o chiamate cell() a larghezza fissa.
  6. Ripetere per documento, prima quelli a rischio più basso; mantenere FPDF installato fino all’ultimo passaggio.
  7. Rimuovere FPDF da composer.json dopo il passaggio finale.
  • Fare uno snapshot dell’output di FPDF per documenti rappresentativi prima di cambiare il codice (input golden; i byte differiranno).
  • Per ogni documento migrato, asserire l’accettazione con un proprio controllo (diff visivo + estrazione del testo). Il comportamento cell/font di NextPDF è esercitato da examples/04-text-and-fonts.php più le suite Font e text-output di tests/ di core. L’accettazione della migrazione è specifica del documento e resta responsabilità vostra.
  • Aggiungere un test di regressione per documento migrato.

Ogni affermazione comportamentale su NextPDF in questa pagina è supportata da una firma del codice sorgente in-repo, da un esempio o da un architecture decision record (ADR), oppure, per le proprietà del formato PDF, dalle clausole ISO 32000-2 nel citations: del frontmatter e dalla tabella Conformità. Il comportamento di FPDF è asserito solo come «motore indipendente — aspettarsi differenze documentate»; questa pagina non rivendica alcuna parità che un artefatto in-repo non dimostri.

NextPDF behavioral claimIn-repo evidence (path)
AddPage maps to addPage(?PageSize, Orientation): static.src/Core/Concerns/HasPages.php (addPage()).
SetFont($family, $style, $size) maps to setFont(string, string, float): static; ''/'B'/'I'/'BI'/'U' styles.src/Core/Concerns/HasTypography.php (setFont()).
Cell maps to cell($w, $h, $txt, $border, $newLine, $align, $fill): static.src/Core/Concerns/HasTextOutput.php (cell()).
MultiCell maps to multiCell($w, $h, $txt, $border, $align): static (metric-based wrap).src/Core/Concerns/HasTextOutput.php (multiCell(), wrapText()).
Write/Text/Ln map to write()/text()/ln().src/Core/Concerns/HasTextOutput.php (write(), text(), ln()).
SetXY/SetX/SetY/GetX/GetY map directly; SetMargins takes a Margin VO.src/Core/Concerns/HasPages.php (setXY(), getX(), setMargins()); src/ValueObjects/Margin.php ((top, right, bottom, left)).
Image maps to image($file, ?$x, ?$y, ?$w, ?$h): static; rejects scheme/NUL paths.src/Core/Concerns/HasImages.php (image(), assertImageFilePath()).
Line/Rect/SetLineWidth/SetDrawColor/SetFillColor/SetTextColor map directly.src/Core/Concerns/HasDrawing.php (line(), rect(), setLineWidth()); src/Core/Concerns/HasColors.php (setDrawColor(), setFillColor(), setTextColor()).
createStandalone() default page is A4 portrait (595.276 × 841.890 pt).src/Core/Document.php (createStandalone()); src/ValueObjects/PageSize.php (A4()).
Output destination is the OutputDestination enum (Inline/Download/File/String); Output('S')getPdfData(), Output('F', $p)save($p).src/Contracts/OutputDestination.php; src/Core/Concerns/HasOutput.php (output()).
SetTitle/SetAuthor/… map to typed metadata setters; land in the info dictionary / XMP.src/Core/Concerns/HasMetadata.php (setTitle(), setAuthor()); ISO 32000-2 §14 (frontmatter citations:).
Fonts are always embedded as subset programs.src/Core/Concerns/HasTypography.php (buildFontData()); ISO 32000-2 §9 (frontmatter citations:).
Content is emitted single-pass.docs/architecture/adr/ADR-001-stream-based-rendering-pipeline.md.

Entrambi i pacchetti restano installati fino al passaggio finale, quindi il rollback per singolo call site significa ripristinare quel call site al percorso FPDF. Dopo il passaggio finale, il rollback significa ripristinare FPDF e il codice precedente dal version control. Non è coinvolta alcuna migrazione di dati.

Vedere Prestazioni. Il modello a passaggio singolo rimuove qualsiasi costo di buffer trattenuto. Il nuovo costo per documento è la risoluzione eager dei font (passaggio 3), che è cacheable tramite la directory dei font.

  • Trascrivere coordinate in millimetri come punti senza la conversione * 72 / 25.4.
  • Lasciare Output() nell’ordine FPDF ($dest, $name), o passare un carattere anziché l’enum OutputDestination.
  • Trascrivere SetMargins($l, $t, $r) direttamente in Margin (il cui ordine è top, right, bottom, left).
  • Aspettarsi che i file di metriche AddFont portino; mettere invece il TTF/OTF nella directory dei font.
  • Ricorrere a un equivalente di GetStringWidth; usare multiCell() per l’andata a capo.
  • Aspettarsi un output identico a livello di byte/pixel (motori indipendenti — questa guida non rivendica mai un drop-in o una compatibilità al 100%).