Solución de problemas de compat-legacy
De un vistazo
Sección titulada «De un vistazo»La mayoría de los problemas de migración se reducen a unos pocos patrones. Cada caso siguiente indica el síntoma, la causa y la solución. Si hay dudas sobre un método concreto, se puede consultar /integrations/tcpdf-compat/method-coverage/ y la matriz autorizada incluida en el repositorio docs/TCPDF_COVERAGE.md.
El proceso solía detenerse por un error de PDF; ahora se propaga una excepción
Sección titulada «El proceso solía detenerse por un error de PDF; ahora se propaga una excepción»Síntoma. El código que antes detenía la ejecución ante un renderizado defectuoso ahora lanza una RuntimeException no capturada, y la solicitud o el trabajo terminan con error.
Causa. Las llamadas heredadas de TCPDF a Error() invocan die(). En su lugar, el adaptador lanza RuntimeException (por diseño), para que los fallos sean observables.
Solución. Envolver los puntos de entrada de renderizado en try/catch y asignar la excepción al contrato de errores correspondiente. No restaurar el comportamiento de die(). Consultar /integrations/tcpdf-compat/production-usage/ § Gestión de fallos.
new \TCPDF() sigue resolviéndose a la biblioteca TCPDF real
Sección titulada «new \TCPDF() sigue resolviéndose a la biblioteca TCPDF real»Síntoma. Se habilitó LegacyBootstrap::enableAliases(), pero la salida sigue pareciéndose a la del TCPDF heredado, o el comportamiento no cambió.
Causa. enableAliases() registra un alias solo si aún no existe ninguna clase con ese nombre. Si tecnickcom/tcpdf todavía puede autocargarse y su \TCPDF se carga primero, el alias se omite y el código sigue usando el TCPDF heredado.
Solución. Durante la migración, preferir importaciones explícitas por archivo (use NextPDF\Compat\Tcpdf\TCPDF;) para que cada punto de llamada sea inequívoco. Eliminar tecnickcom/tcpdf una vez superada la auditoría (consultar /integrations/tcpdf-compat/migration/ Etapa 5). No ejecutar ambas bibliotecas con los alias globales habilitados en el mismo proceso.
Un método «funciona», pero el parámetro que pasé se ignora
Sección titulada «Un método «funciona», pero el parámetro que pasé se ignora»Síntoma. Una llamada se ejecuta correctamente y genera un PDF, pero una opción pasada (enlace de imagen, alineación, PPP, color de marcador, …) no surte efecto.
Causa. El método pertenece al conjunto de métodos que ignoran parámetros en silencio. Acepta el parámetro por compatibilidad con el código fuente y luego lo descarta. Es un comportamiento documentado, no un error: consultar /integrations/tcpdf-compat/method-coverage/ §2.
Solución. Ejecutar una auditoría en modo estricto para encontrar todas las llamadas de este tipo:
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\Exception\TcpdfNotImplementedException;use NextPDF\Compat\Tcpdf\TCPDF;
$pdf = new TCPDF();$pdf->setStrictMode(true);$pdf->AddPage();$pdf->SetFont('helvetica', '', 12);
try { $pdf->Image('logo.png', 10, 10, 50, 0, '', 'https://example.com');} catch (TcpdfNotImplementedException $e) { // Message lists every ignored parameter and a migration hint. echo $e->getMessage(), "\n";}Después, eliminar el parámetro o expresarlo de nuevo mediante la API moderna ($pdf->getDocument()), como en /integrations/tcpdf-compat/migration/ Etapa 4.
El valor de retorno de MultiCell() siempre es 1
Sección titulada «El valor de retorno de MultiCell() siempre es 1»Síntoma. El código que se bifurca según el valor de retorno de MultiCell() (por ejemplo, para calcular la altura usada o el número de líneas) se comporta de forma incorrecta.
Causa. El MultiCell() del adaptador devuelve el marcador de posición de compatibilidad 1, no el número de celdas/líneas renderizadas. Write() también devuelve 0.
Solución. No basar ramificaciones en estos valores de retorno. Si se necesita la altura renderizada, calcularla a partir de getStringHeight() / getNumLines(), o trasladar esa lógica a la API moderna.
setPDFVersion('1.4') no produjo un archivo PDF 1.4
Sección titulada «setPDFVersion('1.4') no produjo un archivo PDF 1.4»Síntoma. Se solicitó una versión de PDF más antigua; la salida sigue siendo PDF 2.0.
Causa. La salida siempre es PDF 2.0 (ISO 32000-2). setPDFVersion() pertenece al conjunto de métodos no aplicables; el adaptador emite un aviso y continúa.
Solución. Eliminar la llamada. Si un consumidor posterior requiere una versión de PDF más antigua, resolver esa restricción del consumidor por separado; el adaptador no puede generar una versión inferior.
setSignature() no hizo nada: el PDF no está firmado
Sección titulada «setSignature() no hizo nada: el PDF no está firmado»Síntoma. Se llamó a setSignature() con un certificado; el PDF de salida no tiene firma.
Causa. setSignature() no está implementado en el motor principal a través de este adaptador. En el modo predeterminado no realiza ninguna operación; en el modo estricto lanza una excepción.
Solución. Para firmar se requiere una edición comercial de NextPDF y la API de firma moderna. Consultar /integrations/tcpdf-compat/security-and-operations/ § Firmas digitales. No esperar que la llamada heredada setSignature() firme nada.
Output() dañó la respuesta HTTP o la salida de un proceso de trabajo
Sección titulada «Output() dañó la respuesta HTTP o la salida de un proceso de trabajo»Síntoma. Datos binarios ilegibles en una respuesta HTTP, o un registro de un proceso de trabajo contaminado con bytes de PDF.
Causa. Se usó un destino de salida que escribe en el canal de salida (I/D) en un contexto donde la respuesta se controla de forma explícita. El adaptador no escribe en el búfer como lo hace el TCPDF heredado, pero I/D siguen activando la salida del motor.
Solución. En procesos de trabajo y gestores propios, usar Output($path, 'F') para escribir un archivo, o Output($name, 'S') para obtener los bytes y emitirlos directamente. La asignación de destinos (sin distinguir mayúsculas/minúsculas y con los espacios en blanco recortados) se verifica en tests/Unit/Compat/Tcpdf/Bridge/OutputBridgeTest.php:
| Código | Devuelve | Efecto secundario |
|---|---|---|
S | bytes del PDF (%PDF…) | ninguno |
F | cadena vacía | escribe el archivo |
E | cuerpo MIME en base64 | ninguno |
FI / FD | cadena vacía | escribe el archivo y luego emite la salida del motor |
I / D / desconocido | cadena vacía | salida del motor (en línea/descarga) |
Las aserciones byte a byte exactas del PDF fallan tras el cambio
Sección titulada «Las aserciones byte a byte exactas del PDF fallan tras el cambio»Síntoma. Las pruebas de instantáneas que comparan los bytes brutos del PDF fallan en todos los casos.
Causa. El motor es una implementación independiente de PDF 2.0. La salida visible es compatible con los métodos delegados, pero los bytes difieren. Este es el comportamiento esperado.
Solución. Actualizar la línea base para que la aserción compruebe el contenido renderizado (texto extraído), la estructura (número de páginas, tamaño de página) o una comprobación rápida (str_starts_with($bytes, '%PDF')). Consultar /integrations/tcpdf-compat/migration/ Etapa 4.
Una constante heredada K_* / PDF_* tiene el valor incorrecto
Sección titulada «Una constante heredada K_* / PDF_* tiene el valor incorrecto»Síntoma. Una ruta personalizada o un valor predeterminado definido mediante una constante no surte efecto.
Causa. El adaptador define automáticamente una constante solo si todavía no está definida, y lo hace al construir la primera instancia. Si define() se ejecuta después de construir el primer adaptador, el valor predeterminado del adaptador ya ha prevalecido.
Solución. Definir todas las constantes K_* / PDF_* personalizadas durante el arranque, antes de crear cualquier instancia del adaptador. Consultar /integrations/tcpdf-compat/configuration/ § Orden de resolución de la configuración.
Discrepancia de versión del motor durante la construcción
Sección titulada «Discrepancia de versión del motor durante la construcción»Síntoma. La construcción falla o se comporta de forma inesperada tras una actualización de dependencias.
Causa. El adaptador requiere nextpdf/core ^3.0. Una versión del núcleo resuelta fuera de ese rango no es compatible.
Solución. Ejecutar composer show nextpdf/core y fijar el motor en ^3.0. Consultar /integrations/tcpdf-compat/install/ § Verificar la versión del motor.
Referencia rápida de diagnóstico
Sección titulada «Referencia rápida de diagnóstico»| Pregunta | Dónde consultar |
|---|---|
| ¿Qué hace realmente el método X aquí? | /integrations/tcpdf-compat/method-coverage/, docs/TCPDF_COVERAGE.md |
| ¿Qué llamadas pierden parámetros? | Auditoría en modo estricto (esta página; /integrations/tcpdf-compat/migration/) |
| ¿Por qué no se detuvo el proceso ante el error? | /integrations/tcpdf-compat/security-and-operations/ § Comportamientos reforzados |
| ¿Por qué la salida no está firmada / no es PDF/A? | /integrations/tcpdf-compat/security-and-operations/ |
| Conflicto entre alias e importación explícita | Esta página; /integrations/tcpdf-compat/boot-and-discovery/ |
Véase también
Sección titulada «Véase también»- /integrations/tcpdf-compat/migration/ — la migración por etapas que evita la mayoría de los problemas anteriores
- /integrations/tcpdf-compat/method-coverage/ — referencia de comportamiento por método
- /integrations/tcpdf-compat/boot-and-discovery/ — registro de alias y prevención de conflictos
docs/TCPDF_COVERAGE.md— matriz de cobertura autorizada