Aller au contenu
getnextpdf.com

Migrer de FPDF vers NextPDF

Ce guide t’aide à faire migrer une base de code reposant sur FPDF vers le cœur de NextPDF. FPDF est l’une des bibliothèques PHP héritées les plus déployées au format Portable Document Format (PDF), et sa surface de dessin — AddPage, SetFont, Cell, MultiCell, Write, Text, Image, Output pilotés par un curseur x/y manuel — correspond proprement à l’API cell/text de NextPDF, parce que les méthodes de dessin de bas niveau de NextPDF suivent la même lignée FPDF/TCPDF. NextPDF n’est pas un clone FPDF prêt à l’emploi, toutefois : c’est un moteur PDF 2.0 moderne avec typage strict, sous-ensemble de polices, signature, PDF/A et accessibilité (PDF balisé). Les deux véritables changements sont le modèle d’unité (NextPDF travaille en points PDF ; FPDF utilise par défaut les millimètres) et les verbes de sortie (une énumération OutputDestination typée au lieu des caractères 'I'/'D'/'F'/'S' de FPDF).

Il n’existe pas de classe-passerelle FPDF dans le cœur. Réécris chaque site d’appel à l’aide de la correspondance des verbes. Si tu veux le plus petit changement initial pour une base de code TCPDF 6.x à la place, vois l’adaptateur de compatibilité TCPDF, qui fournit un chemin prêt à l’emploi quasi compatible avec la source ; FPDF n’a pas d’adaptateur de ce genre.

Fenêtre de terminal
composer require nextpdf/core:^3

Garde setasign/fpdf (ou ton fpdf/fpdf) installé pendant la migration. Supprime-le après la bascule finale (voir la séquence de migration sûre).

FPDF et NextPDF partagent le même modèle mental : un document fait de pages, un curseur (la position x/y courante) et des verbes qui dessinent à cette position ou la font avancer. SetXY, Cell, Ln et MultiCell lisent et modifient tous le curseur dans les deux bibliothèques, donc la plupart du code FPDF procédural se traduit ligne pour ligne.

Les différences sont délibérées, pas accidentelles :

  • Unités. Le constructeur de FPDF (new FPDF($orientation, $unit, $size)) utilise par défaut les millimètres. NextPDF travaille en points PDF (1 pt = 1/72 in, ISO 32000-2 §7). Il n’y a pas de réglage d’unité à l’échelle du document — convertis les mm en points une seule fois (pt = mm * 72 / 25.4).
  • Le sens de Y reste le même pour toi. Comme FPDF, les coordonnées utilisateur de NextPDF placent y = 0 en haut de la page et augmentent vers le bas, donc l’arithmétique du curseur se porte directement. NextPDF convertit en interne vers l’origine PDF native en bas à gauche.
  • La construction est explicite. FPDF replie l’orientation, l’unité et la taille dans le constructeur ; NextPDF prend un objet valeur immuable NextPDF\Core\Config (taille de page, marges, répertoire de polices) et un addPage() explicite.
  • Toujours Unicode, toujours en sous-ensemble. Le build de base de FPDF est en Latin-1 et a besoin de la variante tFPDF/UTF-8 pour Unicode. NextPDF est en UTF-8 de bout en bout et embarque toujours les polices sous forme de programmes en sous-ensemble (ISO 32000-2 §9). Les fichiers AddFont/de métriques de polices de FPDF n’ont aucun analogue ; enregistre un répertoire de polices TrueType/OpenType et sélectionne la famille par son nom.

Les points d’entrée du cœur utilisés ci-dessous sont Document::createStandalone(), Document::addPage(), Document::setFont(), Document::cell(), Document::multiCell(), Document::text(), Document::write(), Document::ln(), Document::image(), les accesseurs de curseur (setXY/setX/ setY/getX/getY), Document::output(?string, OutputDestination), Document::save(string $path): void, Document::getPdfData(): string et l’objet valeur NextPDF\Core\Config. La référence complète de ces méthodes de dessin, de texte et de sortie du cœur se trouve dans les modules du cœur et dans l’index de référence, auto-générée depuis le PHPDoc. Le module Html est une lecture connexe pour le HTML-vers-PDF, non la référence des verbes de cette page.

Les noms de méthodes publiques de FPDF sont anciens et bien connus. La colonne NextPDF ci-dessous est confirmée par les signatures source du cœur (voir Preuves / traçabilité).

FPDFNextPDFNotes
new FPDF($orient, $unit, $size)Document::createStandalone($config)Les arguments orientation/unité/taille du constructeur deviennent une NextPDF\Core\Config (pageSize, margins, fontsDirectory). Pas de $unit — travaille en points. La page par défaut de createStandalone() est A4 portrait.
$pdf->AddPage($orient, $size)$doc->addPage($size, $orientation)Correspondance directe. $size est un objet valeur PageSize ; $orientation est l’énumération Orientation (Portrait/Landscape).
$pdf->SetFont($family, $style, $size)$doc->setFont($family, $style, $size)Correspondance directe. $style utilise les mêmes codes ''/'B'/'I'/'BI' (plus le 'U' souligné).
$pdf->Cell($w, $h, $txt, $border, $ln, $align, $fill)$doc->cell($w, $h, $txt, $border, $newLine, $align, $fill)Correspondance directe. $align est l’énumération Alignment (Left/Center/Right/Justify) ; $border accepte un bool ou une chaîne 'LTRB' ; $ln devient le bool $newLine.
$pdf->MultiCell($w, $h, $txt, $border, $align, $fill)$doc->multiCell($w, $h, $txt, $border, $align)Coupe les mots sur les métriques réelles de la police. Pas d’argument $fill ; peins d’abord un rect() rempli s’il te faut un fond.
$pdf->Write($h, $txt, $link)$doc->write($h, $txt, $link)Texte au fil du curseur ; $link attache une annotation de lien URL.
$pdf->Text($x, $y, $txt)$doc->text($x, $y, $txt)Texte à position absolue. Correspondance directe.
$pdf->Ln($h)$doc->ln($h)Saut de ligne vers la marge gauche ; 0 = hauteur de ligne par défaut.
$pdf->Image($file, $x, $y, $w, $h)$doc->image($file, $x, $y, $w, $h)Correspondance directe ; $x/$y/$w/$h sont nullables (null = curseur courant / taille intrinsèque).
$pdf->SetXY($x, $y) / SetX / SetY$doc->setXY($x, $y) / setX / setYCorrespondance directe. getX()/getY() lisent le curseur.
$pdf->SetMargins($l, $t, $r)$doc->setMargins(new Margin($t, $r, $bottom, $l))Un seul objet valeur Margin ; l’ordre du constructeur est (top, right, bottom, left) — et non le (left, top, right) de FPDF. Le SetMargins de FPDF n’a pas d’argument de marge basse (sa marge basse vient de SetAutoPageBreak($auto, $margin)), donc choisis $bottom toi-même — couramment égal à la marge haute, ou passe la marge de saut de page automatique.
$pdf->SetAutoPageBreak($auto, $margin)$doc->setAutoPageBreak($auto, $margin)Correspondance directe.
$pdf->SetDrawColor / SetFillColor / SetTextColor$doc->setDrawColor / setFillColor / setTextColorRVB (r, g, b), ou une seule valeur pour le niveau de gris.
$pdf->Line / Rect / SetLineWidth$doc->line / rect / setLineWidthCorrespondance directe. rect() prend une chaîne de style ('S'/'F'/'DF').
$pdf->SetTitle/SetAuthor/SetSubject/SetKeywords/SetCreator$doc->setTitle/setAuthor/setSubject/setKeywords/setCreatorCorrespondance directe. Atterrit dans le dictionnaire d’informations / Extensible Metadata Platform (XMP) d’ISO 32000-2 §14.
$pdf->Output($dest, $name)$doc->output($name, OutputDestination::…)Les caractères de destination de FPDF (I/D/F/S) correspondent à l’énumération OutputDestination ; note que l’ordre des arguments s’inverse (le nom d’abord dans NextPDF).
$pdf->Output('S')$doc->getPdfData()Renvoie les octets du PDF.
$pdf->Output('F', $path)$doc->save($path)Écrit vers un chemin de fichier.
$pdf->GetStringWidth($s)(pas de méthode publique)La largeur de chaîne est calculée en interne pendant la coupe de cell()/multiCell() ; il n’y a pas de verbe public de mesure par chaîne. Pilote la coupe via multiCell() plutôt que de mesurer à la main.
<?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";

Cet exemple s’aligne sur examples/04-text-and-fonts.php. Il utilise une taille de page explicite, des marges, un répertoire de polices enregistré et le modèle de cell piloté par le curseur qu’une base de code FPDF utilise déjà.

<?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és. Chaque coordonnée numérique, largeur, hauteur et marge que tu copies de FPDF est en millimètres par défaut. Multiplie par 72 / 25.4 pour obtenir des points, une fois, pendant le portage. Mélanger les deux dimensionne tout de travers silencieusement.
  • Ordre des arguments d’Output(). FPDF, c’est Output($dest, $name) ; NextPDF, c’est output($name, $dest). La destination est l’énumération OutputDestination, pas un caractère. Préfère save() / getPdfData() pour la sortie fichier / chaîne.
  • Ordre de SetMargins. FPDF, c’est (left, top, right) ; l’objet valeur Margin de NextPDF, c’est (top, right, bottom, left). Réordonne, ne transcris pas.
  • Polices. Les fichiers AddFont() + .php de métriques de FPDF n’ont aucun équivalent. Place le fichier TrueType/OpenType dans le répertoire de polices et appelle setFont() avec le nom de la famille. Les noms Base14 du cœur (Helvetica, Times, Courier) se résolvent sans fichier ; sous PDF/A ou PDF balisé, ils sont auto-substitués par une police embarquable.
  • GetStringWidth. Il n’y a pas de méthode publique de mesure de chaîne. Si ton code FPDF mesure des chaînes pour disposer des colonnes à la main, bascule ce bloc vers multiCell() (qui coupe sur les métriques) ou des appels cell() à largeur fixe.

NextPDF émet le contenu en une seule passe en flux (enregistrement de décision d’architecture ADR-001) ; le pic mémoire suit la taille du document, pas un arbre d’objets retenu. Le budget de l’exemple de ce guide est wall_ms: 2000, peak_mb: 128. Pour les longs documents, pilote le contenu au fil des appels addPage() — la même forme de boucle qu’un rapport FPDF utilise déjà.

  • Métadonnées. SetTitle()/SetAuthor() correspondent à des setters typés qui écrivent le dictionnaire d’informations / XMP d’ISO 32000-2 §14. N’y stocke jamais de secrets.
  • Chemins d’images. image() rejette les schémas de wrapper de flux et les octets NUL embarqués avant la lecture. Passe des chemins contrôlés par l’application.
  • Pas de code dans le document. NextPDF n’exécute aucun script dans le document ; rien dans FPDF ne change cela.
ÉnoncéSpécificationClause
Le format/orientation de page correspond à la boîte de délimitation de page.ISO 32000-2§7
Les polices sont écrites sous forme de programmes de police embarqués/en sous-ensemble.ISO 32000-2§9
Le titre / les métadonnées atterrissent dans le dictionnaire d’informations / XMP.ISO 32000-2§14
Les lignes, rectangles et images relèvent du dessin par flux de contenu.ISO 32000-2§8

NextPDF produit du contenu ISO 32000-2 ; il n’affirme aucune identité visuelle avec FPDF. Re-vérifie la sortie chaque fois que tu changes de moteur de rendu.

Sans objet. Le cœur de NextPDF couvre le chemin de migration FPDF décrit ici.


Aux équipes faisant tourner FPDF (ou tFPDF) pour de la génération de PDF côté serveur, procédurale. Si ton code est une suite d’appels AddPage / SetFont / Cell / MultiCell / Image / Output pilotés par SetXY et Ln, la correspondance des verbes couvre toute ta surface.

Dans le périmètre : les verbes de dessin de FPDF, le modèle de curseur, les polices, les couleurs, les lignes et rectangles, les métadonnées et la sortie. Hors périmètre : l’outillage de fichiers de métriques AddFont de FPDF et les extensions de script FPDF tierces (codes-barres, rotation, signets) — fais-les correspondre aux modules NextPDF correspondants (Barcode, Transforms, Navigation), qui ne sont pas couverts ici.

Compatibilité comportementale, pas une passerelle prête à l’emploi : le cœur ne fournit aucune classe-passerelle FPDF. Réécris chaque site d’appel. Les verbes s’alignent étroitement parce que l’API cell/text de NextPDF partage la lignée FPDF/TCPDF, mais le modèle d’unité, l’ordre des arguments d’Output et les types Margin/énumération diffèrent — donc une transcription est fausse, une traduction est juste.

Construction FPDFNextPDFNotes
$unit ('mm' par défaut)(pas d’équivalent)Travaille en points PDF. Convertis les dimensions avec pt = mm * 72 / 25.4 une fois pendant le portage.
$orientation ('P'/'L')énumération Orientation sur addPage(), ou échange largeur/hauteur de PageSizePaysage = largeur > hauteur.
$size ('A4', [w,h])Config->pageSize (objet valeur PageSize)Les formats nommés deviennent des dimensions explicites en points ; les fabriques PageSize::A4()A0() et Letter/Legal existent.
SetMargins($l, $t, $r)Config->margins (Margin VO)Ordre du constructeur (top, right, bottom, left).
AddFont($family, $style, $file)répertoire de polices + setFont() par nomAbandonne le fichier de métriques ; place le TTF/OTF dans Config->fontsDirectory.
  • Répertoires de polices. L’enregistrement AddFont par police de FPDF se réduit à un répertoire de polices plus la correspondance de famille de setFont(). Commence par Config->fontsDirectory (le chemin de recherche par défaut) ; enregistre des répertoires supplémentaires via FontRegistry::addFontDirectory() ou Document::addFontDirectory() quand les polices résident à plusieurs endroits.
  • Toujours Unicode. Pas de Latin-1 par défaut ni de build tFPDF séparé ; l’entrée UTF-8 est la norme.
  • Toujours en sous-ensemble. NextPDF met toujours les polices embarquées en sous-ensemble (ISO 32000-2 §9) ; les choix d’embarquement de polices de FPDF n’ont aucun équivalent et ne sont pas nécessaires.
  • Re-référence les glyphes. La correspondance et le repli des polices sont propres au moteur ; un alias de police FPDF peut nécessiter un nom de famille exact. Les différences de substitution sont attendues, pas des défauts.
  • Conversion d’unité (mm → pt) — l’erreur de portage la plus courante ; voir ci-dessus.
  • L’ordre des arguments d’Output s’inverse et la destination devient une énumération.
  • Margin / Alignment / Orientation sont des objets/énumérations typés, pas des caractères ni des triplets positionnels (l, t, r).
  • Pas de GetStringWidth public — pilote la coupe via multiCell().
  • Rasterisation indépendante — la coupe de ligne et la pagination sur du contenu dense peuvent différer ; re-référence les diffs visuels.

Ce sont des différences de comportement documentées, pas des défauts dans l’un ou l’autre moteur.

  • Le sélecteur $unit de FPDF — non modélisé (toujours des points).
  • Les fichiers de métriques AddFont() + .php/.z — remplacés par un répertoire de polices.
  • GetStringWidth() — pas de verbe public de mesure de chaîne.
  • Les caractères de destination 'I'/'D'/'F'/'S' de FPDF — remplacés par l’énumération OutputDestination + save()/getPdfData().

Le code qui dépend de cela ne « migre » pas tel quel. Réexprime-le avec les lignes ci-dessus.

  1. Ajoute nextpdf/core à côté de FPDF ; garde FPDF installé pour l’instant.
  2. Choisis un document à faible risque. Convertis le constructeur via la carte des unités, puis porte chaque verbe avec la carte des verbes. Convertis chaque coordonnée en mm vers des points.
  3. Place les polices du document dans Config->fontsDirectory et sélectionne-les par nom de famille ; abandonne les appels AddFont.
  4. Génère les deux PDF pour la même entrée et compare-les visuellement. Les différences (substitution de police, coupe de ligne) sont attendues pour des moteurs indépendants — accepte-les par document.
  5. Remplace toute disposition manuelle basée sur GetStringWidth par multiCell() ou des appels cell() à largeur fixe.
  6. Répète par document, du plus faible risque en premier ; garde FPDF installé jusqu’à la dernière bascule.
  7. Retire FPDF de composer.json après la bascule finale.
  • Capture la sortie FPDF pour des documents représentatifs avant de changer le code (entrées de référence ; les octets différeront).
  • Pour chaque document migré, vérifie l’acceptation avec ton propre contrôle (diff visuel + extraction de texte). Le comportement cell/police de NextPDF est exercé par examples/04-text-and-fonts.php plus les suites Font et de sortie de texte des tests/ du cœur. L’acceptation de la migration est spécifique au document et reste ta responsabilité.
  • Ajoute un test de régression par document migré.

Chaque énoncé comportemental de NextPDF sur cette page s’appuie sur une signature source, un exemple ou un enregistrement de décision d’architecture (ADR) du dépôt, ou, pour les propriétés du format PDF, sur les clauses ISO 32000-2 du frontmatter citations: et la table de Conformité. Le comportement de FPDF n’est affirmé que comme « moteur indépendant — attends-toi à des différences documentées » ; cette page ne revendique aucune parité qu’un artefact du dépôt ne prouve pas.

Revendication comportementale NextPDFPreuve dans le dépôt (chemin)
AddPage correspond à addPage(?PageSize, Orientation): static.src/Core/Concerns/HasPages.php (addPage()).
SetFont($family, $style, $size) correspond à setFont(string, string, float): static ; styles ''/'B'/'I'/'BI'/'U'.src/Core/Concerns/HasTypography.php (setFont()).
Cell correspond à cell($w, $h, $txt, $border, $newLine, $align, $fill): static.src/Core/Concerns/HasTextOutput.php (cell()).
MultiCell correspond à multiCell($w, $h, $txt, $border, $align): static (coupe basée sur les métriques).src/Core/Concerns/HasTextOutput.php (multiCell(), wrapText()).
Write/Text/Ln correspondent à write()/text()/ln().src/Core/Concerns/HasTextOutput.php (write(), text(), ln()).
SetXY/SetX/SetY/GetX/GetY correspondent directement ; SetMargins prend un Margin VO.src/Core/Concerns/HasPages.php (setXY(), getX(), setMargins()) ; src/ValueObjects/Margin.php ((top, right, bottom, left)).
Image correspond à image($file, ?$x, ?$y, ?$w, ?$h): static ; rejette les chemins à schéma/NUL.src/Core/Concerns/HasImages.php (image(), assertImageFilePath()).
Line/Rect/SetLineWidth/SetDrawColor/SetFillColor/SetTextColor correspondent directement.src/Core/Concerns/HasDrawing.php (line(), rect(), setLineWidth()) ; src/Core/Concerns/HasColors.php (setDrawColor(), setFillColor(), setTextColor()).
La page par défaut de createStandalone() est A4 portrait (595.276 × 841.890 pt).src/Core/Document.php (createStandalone()) ; src/ValueObjects/PageSize.php (A4()).
La destination de sortie est l’énumération OutputDestination (Inline/Download/File/String) ; Output('S')getPdfData(), Output('F', $p)save($p).src/Contracts/OutputDestination.php ; src/Core/Concerns/HasOutput.php (output()).
SetTitle/SetAuthor/… correspondent à des setters de métadonnées typés ; atterrissent dans le dictionnaire d’informations / XMP.src/Core/Concerns/HasMetadata.php (setTitle(), setAuthor()) ; ISO 32000-2 §14 (frontmatter citations:).
Les polices sont toujours embarquées sous forme de programmes en sous-ensemble.src/Core/Concerns/HasTypography.php (buildFontData()) ; ISO 32000-2 §9 (frontmatter citations:).
Le contenu est émis en une seule passe.docs/architecture/adr/ADR-001-stream-based-rendering-pipeline.md.

Les deux paquets restent installés jusqu’à la bascule finale, donc un rollback par site d’appel signifie revenir ce site d’appel au chemin FPDF. Après la bascule finale, le rollback signifie restaurer FPDF et le code antérieur depuis le contrôle de version. Aucune migration de données n’est en jeu.

Vois Performance. Le modèle en une seule passe supprime tout coût de buffer retenu. Le nouveau coût par document est la résolution anticipée des polices (étape 3), qui est cachable via le répertoire de polices.

  • Transcrire les coordonnées en millimètres comme des points sans la conversion * 72 / 25.4.
  • Laisser Output() dans l’ordre ($dest, $name) de FPDF, ou passer un caractère au lieu de l’énumération OutputDestination.
  • Transcrire SetMargins($l, $t, $r) directement dans Margin (dont l’ordre est top, right, bottom, left).
  • S’attendre à ce que les fichiers de métriques AddFont se portent ; place le TTF/OTF dans le répertoire de polices à la place.
  • Chercher un équivalent de GetStringWidth ; utilise multiCell() pour la coupe.
  • S’attendre à une sortie identique octet par octet / pixel par pixel (moteurs indépendants — ce guide ne revendique jamais un prêt-à-l’emploi ni une compatibilité à 100 %).