Ir al contenido
getnextpdf.com

Migrar de FPDF a NextPDF

Esta guía te ayuda a trasladar un código base basado en FPDF al núcleo de NextPDF. FPDF es una de las bibliotecas heredadas de formato de documento portátil (PDF) en PHP más desplegadas, y su superficie de dibujo —AddPage, SetFont, Cell, MultiCell, Write, Text, Image, Output gobernada por un cursor x/y manual— se asigna limpiamente a la propia API de celdas/texto de NextPDF, porque los métodos de dibujo de bajo nivel de NextPDF siguen el mismo linaje FPDF/TCPDF. NextPDF no es un clon de FPDF listo para sustituir, eso sí: es un motor moderno de PDF 2.0 con tipos estrictos, subdivisión de fuentes, firma, PDF/A y accesibilidad (PDF etiquetado). Los dos cambios reales son el modelo de unidades (NextPDF trabaja en puntos de PDF; FPDF usa milímetros de forma predeterminada) y los verbos de salida (un enum OutputDestination tipado en lugar de los caracteres 'I'/'D'/'F'/'S' de FPDF).

No hay ningún shim de clase FPDF en el núcleo. Reescribe cada punto de llamada usando la asignación de verbos. Si quieres el cambio inicial más pequeño para un código base de TCPDF 6.x, consulta en su lugar el adaptador de compatibilidad con TCPDF, que incluye una vía de sustitución casi compatible a nivel de código fuente; FPDF no tiene ese adaptador.

Ventana de terminal
composer require nextpdf/core:^3

Mantén setasign/fpdf (o tu fpdf/fpdf) instalado mientras migras. Elimínalo tras el cambio final (consulta la secuencia de migración segura).

FPDF y NextPDF comparten el mismo modelo mental: un documento hecho de páginas, un cursor (la posición x/y actual) y verbos que dibujan en ese cursor o lo avanzan. SetXY, Cell, Ln y MultiCell leen y mutan el cursor en ambas bibliotecas, así que la mayor parte del código procedural de FPDF se traduce línea por línea.

Las diferencias son deliberadas, no accidentales:

  • Unidades. El constructor de FPDF (new FPDF($orientation, $unit, $size)) usa milímetros de forma predeterminada. NextPDF trabaja en puntos de PDF (1 pt = 1/72 in, ISO 32000-2 §7). No hay un control de unidades para todo el documento: convierte mm a puntos una vez (pt = mm * 72 / 25.4).
  • La dirección Y se mantiene igual para ti. Como FPDF, las coordenadas de usuario de NextPDF colocan y = 0 en la parte superior de la página y aumentan hacia abajo, así que la aritmética del cursor se porta directamente. NextPDF convierte internamente al origen inferior-izquierdo nativo de PDF.
  • La construcción es explícita. FPDF pliega la orientación, la unidad y el tamaño en el constructor; NextPDF recibe un objeto de valor inmutable NextPDF\Core\Config (tamaño de página, márgenes, directorio de fuentes) y un addPage() explícito.
  • Siempre Unicode, siempre subconjunto. La compilación de núcleo de FPDF es Latin-1 y necesita la variante tFPDF/UTF-8 para Unicode. NextPDF es UTF-8 de principio a fin y siempre incrusta las fuentes como programas de subconjunto (ISO 32000-2 §9). Los archivos AddFont/de métricas de fuente de FPDF no tienen análogo; registra un directorio de fuentes TrueType/OpenType y selecciona la familia por nombre.

Los puntos de entrada del núcleo usados abajo son Document::createStandalone(), Document::addPage(), Document::setFont(), Document::cell(), Document::multiCell(), Document::text(), Document::write(), Document::ln(), Document::image(), los accesores de cursor (setXY/setX/ setY/getX/getY), Document::output(?string, OutputDestination), Document::save(string $path): void, Document::getPdfData(): string y el objeto de valor NextPDF\Core\Config. La referencia completa de estos métodos de dibujo, texto y salida del núcleo vive en los módulos del núcleo y en el índice de referencia, generados automáticamente a partir de PHPDoc. El módulo Html es lectura relacionada para HTML a PDF, no la referencia de los verbos de esta página.

Los nombres de los métodos públicos de FPDF son consolidados y bien conocidos. La columna de NextPDF de abajo está confirmada frente a las firmas del código fuente del núcleo (consulta Evidencia / trazabilidad).

FPDFNextPDFNotas
new FPDF($orient, $unit, $size)Document::createStandalone($config)Los argumentos orientation/unit/size del constructor se vuelven un NextPDF\Core\Config (pageSize, margins, fontsDirectory). Sin $unit: trabaja en puntos. La página predeterminada de createStandalone() es A4 vertical.
$pdf->AddPage($orient, $size)$doc->addPage($size, $orientation)Mapa directo. $size es un objeto de valor PageSize; $orientation es el enum Orientation (Portrait/Landscape).
$pdf->SetFont($family, $style, $size)$doc->setFont($family, $style, $size)Mapa directo. $style usa los mismos códigos ''/'B'/'I'/'BI' (más 'U' de subrayado).
$pdf->Cell($w, $h, $txt, $border, $ln, $align, $fill)$doc->cell($w, $h, $txt, $border, $newLine, $align, $fill)Mapa directo. $align es el enum Alignment (Left/Center/Right/Justify); $border acepta bool o una cadena 'LTRB'; $ln se vuelve el bool $newLine.
$pdf->MultiCell($w, $h, $txt, $border, $align, $fill)$doc->multiCell($w, $h, $txt, $border, $align)Ajusta por palabras según las métricas reales de la fuente. Sin argumento $fill; pinta primero un rect() relleno si necesitas un fondo.
$pdf->Write($h, $txt, $link)$doc->write($h, $txt, $link)Texto fluido desde el cursor; $link adjunta una anotación de enlace de URL.
$pdf->Text($x, $y, $txt)$doc->text($x, $y, $txt)Texto en posición absoluta. Mapa directo.
$pdf->Ln($h)$doc->ln($h)Salto de línea al margen izquierdo; 0 = altura de línea predeterminada.
$pdf->Image($file, $x, $y, $w, $h)$doc->image($file, $x, $y, $w, $h)Mapa directo; $x/$y/$w/$h admiten null (null = cursor actual / tamaño intrínseco).
$pdf->SetXY($x, $y) / SetX / SetY$doc->setXY($x, $y) / setX / setYMapa directo. getX()/getY() leen el cursor.
$pdf->SetMargins($l, $t, $r)$doc->setMargins(new Margin($t, $r, $bottom, $l))Un objeto de valor Margin; el orden del constructor es (top, right, bottom, left)no el (left, top, right) de FPDF. El SetMargins de FPDF no tiene argumento inferior (su margen inferior proviene de SetAutoPageBreak($auto, $margin)), así que elige tú $bottom —comúnmente igual al margen superior, o pasa el margen de salto de página automático.
$pdf->SetAutoPageBreak($auto, $margin)$doc->setAutoPageBreak($auto, $margin)Mapa directo.
$pdf->SetDrawColor / SetFillColor / SetTextColor$doc->setDrawColor / setFillColor / setTextColorRGB (r, g, b), o un único valor para escala de grises.
$pdf->Line / Rect / SetLineWidth$doc->line / rect / setLineWidthMapa directo. rect() recibe una cadena de estilo ('S'/'F'/'DF').
$pdf->SetTitle/SetAuthor/SetSubject/SetKeywords/SetCreator$doc->setTitle/setAuthor/setSubject/setKeywords/setCreatorMapa directo. Queda en el diccionario de información de la §14 de ISO 32000-2 / Plataforma de Metadatos Extensible (XMP).
$pdf->Output($dest, $name)$doc->output($name, OutputDestination::…)Los caracteres de destino de FPDF (I/D/F/S) se asignan al enum OutputDestination; ten en cuenta que el orden de los argumentos se invierte (nombre primero en NextPDF).
$pdf->Output('S')$doc->getPdfData()Devuelve los bytes del PDF.
$pdf->Output('F', $path)$doc->save($path)Escribe en una ruta de archivo.
$pdf->GetStringWidth($s)(sin método público)El ancho de cadena se calcula internamente durante el ajuste de cell()/multiCell(); no hay verbo público de medición por cadena. Gobierna el ajuste mediante multiCell() en lugar de medir 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";

Este ejemplo se alinea con examples/04-text-and-fonts.php. Usa un tamaño de página explícito, márgenes, un directorio de fuentes registrado y el modelo de celdas gobernado por el cursor que un código base de FPDF ya 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);
  • Unidades. Cada coordenada numérica, ancho, alto y margen que copies de FPDF está en milímetros de forma predeterminada. Multiplica por 72 / 25.4 para obtener puntos, una sola vez, durante el porte. Mezclar ambos dimensiona mal todo de forma silenciosa.
  • Orden de argumentos de Output(). FPDF es Output($dest, $name); NextPDF es output($name, $dest). El destino es el enum OutputDestination, no un carácter. Prefiere save() / getPdfData() para salida a archivo / cadena.
  • Orden de SetMargins. FPDF es (left, top, right); el objeto de valor Margin de NextPDF es (top, right, bottom, left). Reordena, no transcribas.
  • Fuentes. El AddFont() + los archivos de métricas .php de FPDF no tienen equivalente. Pon el archivo TrueType/OpenType en el directorio de fuentes y llama a setFont() con el nombre de familia. Los nombres Base14 del núcleo (Helvetica, Times, Courier) se resuelven sin archivo; bajo PDF/A o PDF etiquetado se sustituyen automáticamente por una fuente incrustable.
  • GetStringWidth. No hay método público de medición de cadenas. Si tu código de FPDF mide cadenas para maquetar columnas a mano, cambia ese bloque a multiCell() (que ajusta según las métricas) o a llamadas de cell() de ancho fijo.

NextPDF emite el contenido en una única pasada de streaming (registro de decisión de arquitectura ADR-001); la memoria pico sigue el tamaño del documento, no un árbol de objetos retenido. El presupuesto del ejemplo de esta guía es wall_ms: 2000, peak_mb: 128. Para documentos largos, gobierna el contenido a través de llamadas a addPage() —la misma forma de bucle que un informe de FPDF ya usa.

  • Metadatos. SetTitle()/SetAuthor() se asignan a setters tipados que escriben el diccionario de información de la §14 de ISO 32000-2 / XMP. Nunca almacenes secretos ahí.
  • Rutas de imagen. image() rechaza esquemas de stream-wrapper y bytes NUL incrustados antes de leer. Pasa rutas controladas por la aplicación.
  • Sin código dentro del documento. NextPDF no ejecuta ningún script dentro del documento; nada en FPDF cambia eso.
AfirmaciónEspecificaciónCláusula
El formato/orientación de página se asignan a la caja de límites de la página.ISO 32000-2§7
Las fuentes se escriben como programas de fuente incrustados/subconjunto.ISO 32000-2§9
El título / los metadatos quedan en el diccionario de información / XMP.ISO 32000-2§14
Las líneas, los rectángulos y las imágenes son pintura del flujo de contenido.ISO 32000-2§8

NextPDF produce contenido ISO 32000-2; no afirma identidad visual con FPDF. Vuelve a revisar la salida siempre que cambies de renderizador.

No aplica. El núcleo de NextPDF cubre la vía de migración de FPDF descrita aquí.


Detalle de migración (secciones requeridas R6)

Sección titulada «Detalle de migración (secciones requeridas R6)»

Equipos que ejecutan FPDF (o tFPDF) para generación de PDF procedural del lado del servidor. Si tu código es una secuencia de llamadas AddPage / SetFont / Cell / MultiCell / Image / Output gobernadas por SetXY y Ln, la asignación de verbos cubre toda tu superficie.

En alcance: los verbos de dibujo de FPDF, el modelo de cursor, las fuentes, los colores, las líneas y los rectángulos, los metadatos y la salida. Fuera de alcance: la herramienta de archivos de métricas AddFont de FPDF y las extensiones de script de FPDF de terceros (códigos de barras, rotación, marcadores) —asígnalas a los módulos correspondientes de NextPDF (Barcode, Transforms, Navigation), que no se cubren aquí.

Compatibilidad de comportamiento, no un shim de sustitución: el núcleo no proporciona ningún shim de clase FPDF. Reescribe cada punto de llamada. Los verbos se alinean estrechamente porque la API de celdas/texto de NextPDF comparte el linaje FPDF/TCPDF, pero el modelo de unidades, el orden de argumentos de Output y los tipos Margin/enum difieren —así que una transcripción está mal, una traducción está bien.

Construcción de FPDFNextPDFNotas
$unit ('mm' predeterminado)(sin equivalente)Trabaja en puntos de PDF. Convierte las dimensiones con pt = mm * 72 / 25.4 una vez durante el porte.
$orientation ('P'/'L')enum Orientation en addPage(), o intercambia ancho/alto de PageSizeHorizontal = ancho > alto.
$size ('A4', [w,h])Config->pageSize (objeto de valor PageSize)Los formatos con nombre se vuelven dimensiones explícitas en puntos; existen las factorías PageSize::A4()A0() y Letter/Legal.
SetMargins($l, $t, $r)Config->margins (Margin VO)Orden del constructor (top, right, bottom, left).
AddFont($family, $style, $file)directorio de fuentes + setFont() por nombreDescarta el archivo de métricas; coloca el TTF/OTF en Config->fontsDirectory.
  • Directorios de fuentes. El registro por fuente AddFont de FPDF se colapsa en un directorio de fuentes más la coincidencia de familia de setFont(). Empieza con Config->fontsDirectory (la ruta de búsqueda predeterminada); registra directorios adicionales mediante FontRegistry::addFontDirectory() o Document::addFontDirectory() cuando las fuentes vivan en más de un sitio.
  • Siempre Unicode. Sin predeterminado Latin-1 y sin compilación tFPDF aparte; la entrada UTF-8 es la norma.
  • Siempre subconjunto. NextPDF siempre subdivide las fuentes incrustadas (ISO 32000-2 §9); las opciones de incrustación de fuentes de FPDF no tienen equivalente y no son necesarias.
  • Rebaselina los glifos. La coincidencia y el respaldo de fuentes son específicos del motor; un alias de fuente de FPDF puede necesitar un nombre de familia exacto. Las diferencias de sustitución son esperadas, no defectos.
  • Conversión de unidades (mm → pt) —el error de porte más común; consulta arriba.
  • El orden de argumentos de Output se invierte y el destino se vuelve un enum.
  • Margin / Alignment / Orientation son objetos/enums tipados, no caracteres ni tríos posicionales (l, t, r).
  • Sin GetStringWidth público —gobierna el ajuste mediante multiCell().
  • Rasterización independiente —el ajuste de línea y la paginación en contenido denso pueden diferir; rebaselina las diferencias visuales.

Estas son diferencias de comportamiento documentadas, no defectos en ninguno de los dos motores.

  • Selector $unit de FPDF —no modelado (siempre puntos).
  • AddFont() + archivos de métricas .php/.z —reemplazados por un directorio de fuentes.
  • GetStringWidth() —sin verbo público de medición de cadenas.
  • Los caracteres de destino 'I'/'D'/'F'/'S' de FPDF —reemplazados por el enum OutputDestination + save()/getPdfData().

El código que depende de estos no «migra» literalmente. Reexprésalo con las filas de arriba.

  1. Añade nextpdf/core junto a FPDF; mantén FPDF instalado por ahora.
  2. Elige un documento de bajo riesgo. Convierte el constructor mediante el mapa de unidades, luego porta cada verbo con el mapa de verbos. Convierte cada coordenada en mm a puntos.
  3. Coloca las fuentes del documento en Config->fontsDirectory y selecciónalas por nombre de familia; descarta las llamadas a AddFont.
  4. Genera ambos PDF para la misma entrada y compáralos visualmente. Las diferencias (sustitución de fuentes, ajuste de línea) son esperadas para motores independientes —acéptalas por documento.
  5. Reemplaza cualquier maquetación manual basada en GetStringWidth por multiCell() o llamadas de cell() de ancho fijo.
  6. Repite por documento, primero el de menor riesgo; mantén FPDF instalado hasta el último cambio.
  7. Elimina FPDF de composer.json tras el cambio final.
  • Toma un snapshot de la salida de FPDF para documentos representativos antes de cambiar el código (entradas golden; los bytes diferirán).
  • Para cada documento migrado, asercia la aceptación con tu propia comprobación (diferencia visual + extracción de texto). El comportamiento de celdas/fuentes de NextPDF lo ejercitan examples/04-text-and-fonts.php más las suites de Font y de salida de texto del núcleo tests/. La aceptación de la migración es específica del documento y sigue siendo tu responsabilidad.
  • Añade una prueba de regresión por documento migrado.

Cada afirmación de comportamiento de NextPDF en esta página está respaldada por una firma de origen, un ejemplo o un registro de decisión de arquitectura (ADR) dentro del repositorio; o, para las propiedades del formato PDF, por las cláusulas de ISO 32000-2 de las citations: del frontmatter y la tabla de Conformidad. El comportamiento de FPDF se afirma solo como «motor independiente: espera diferencias documentadas»; esta página no reclama ninguna paridad que un artefacto dentro del repositorio no demuestre.

Afirmación de comportamiento de NextPDFEvidencia dentro del repositorio (ruta)
AddPage se asigna a addPage(?PageSize, Orientation): static.src/Core/Concerns/HasPages.php (addPage()).
SetFont($family, $style, $size) se asigna a setFont(string, string, float): static; estilos ''/'B'/'I'/'BI'/'U'.src/Core/Concerns/HasTypography.php (setFont()).
Cell se asigna a cell($w, $h, $txt, $border, $newLine, $align, $fill): static.src/Core/Concerns/HasTextOutput.php (cell()).
MultiCell se asigna a multiCell($w, $h, $txt, $border, $align): static (ajuste basado en métricas).src/Core/Concerns/HasTextOutput.php (multiCell(), wrapText()).
Write/Text/Ln se asignan a write()/text()/ln().src/Core/Concerns/HasTextOutput.php (write(), text(), ln()).
SetXY/SetX/SetY/GetX/GetY se asignan directamente; SetMargins recibe un Margin VO.src/Core/Concerns/HasPages.php (setXY(), getX(), setMargins()); src/ValueObjects/Margin.php ((top, right, bottom, left)).
Image se asigna a image($file, ?$x, ?$y, ?$w, ?$h): static; rechaza rutas con esquema/NUL.src/Core/Concerns/HasImages.php (image(), assertImageFilePath()).
Line/Rect/SetLineWidth/SetDrawColor/SetFillColor/SetTextColor se asignan directamente.src/Core/Concerns/HasDrawing.php (line(), rect(), setLineWidth()); src/Core/Concerns/HasColors.php (setDrawColor(), setFillColor(), setTextColor()).
La página predeterminada de createStandalone() es A4 vertical (595.276 × 841.890 pt).src/Core/Document.php (createStandalone()); src/ValueObjects/PageSize.php (A4()).
El destino de salida es el enum 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/… se asignan a setters de metadatos tipados; quedan en el diccionario de información / XMP.src/Core/Concerns/HasMetadata.php (setTitle(), setAuthor()); ISO 32000-2 §14 (citations: del frontmatter).
Las fuentes siempre se incrustan como programas de subconjunto.src/Core/Concerns/HasTypography.php (buildFontData()); ISO 32000-2 §9 (citations: del frontmatter).
El contenido se emite en una sola pasada.docs/architecture/adr/ADR-001-stream-based-rendering-pipeline.md.

Ambos paquetes permanecen instalados hasta el cambio final, así que la reversión por punto de llamada significa revertir ese punto de llamada a la vía de FPDF. Tras el cambio final, la reversión significa restaurar FPDF y el código anterior desde el control de versiones. No hay ninguna migración de datos involucrada.

Consulta Rendimiento. El modelo de una sola pasada elimina cualquier coste de búfer retenido. El nuevo coste por documento es la resolución anticipada de fuentes (paso 3), que se puede almacenar en caché mediante el directorio de fuentes.

  • Transcribir coordenadas en milímetros como puntos sin la conversión * 72 / 25.4.
  • Dejar Output() en el orden ($dest, $name) de FPDF, o pasar un carácter en lugar del enum OutputDestination.
  • Transcribir SetMargins($l, $t, $r) directamente a Margin (cuyo orden es top, right, bottom, left).
  • Esperar que los archivos de métricas de AddFont se porten; coloca el TTF/OTF en el directorio de fuentes en su lugar.
  • Recurrir a un equivalente de GetStringWidth; usa multiCell() para el ajuste.
  • Esperar una salida idéntica byte a byte/píxel a píxel (motores independientes: esta guía nunca reclama una sustitución directa ni compatibilidad del 100 %).