Ir al contenido
getnextpdf.com

Un motor, todos los frameworks

Spec: PSR-11 Container, §1.1.2Spec: PSR-4 Autoloader, §3

La mayoría de los entornos PHP en crecimiento acaban con más de un framework. NextPDF es un único motor PDF que se encuentra con cada uno en sus propios términos: puentes idiomáticos para Laravel, Symfony y CodeIgniter, además de una vía autónoma para el código que no se ejecuta en ninguno de ellos. El modelo de documento es compartido. Solo cambia la forma en que lo llamas.

Una biblioteca PDF distinta por stack es un impuesto silencioso. Cada una tiene sus propias rarezas, su propio tratamiento de fuentes, su propia idea de qué significa válido. Una factura que se renderiza correctamente desde el servicio de Laravel puede renderizarse de forma sutilmente distinta desde el worker de Symfony, porque la dibujó una biblioteca diferente. Ahora tu destino de archivado, la ubicación de tu firma y tus etiquetas de accesibilidad dependen de qué equipo entregó el documento. El informe de error dice «el PDF está mal», y la respuesta depende de cuál de los tres motores lo produjo.

Estandarizar un único motor colapsa esa superficie. Hay un solo lugar donde se decide un perfil PDF/A, un único pipeline de fuentes que certificar, un único validador en el que confiar. El framework en el que te encuentres deja de ser una variable en si el documento es correcto.

  • El motor del núcleo es agnóstico al framework. nextpdf/core no sabe nada de HTTP, enrutamiento ni cableado de contenedor. Es un motor PDF 2.0 y nada más.
  • Cada puente adapta, no reimplementa. Los paquetes de Laravel, Symfony y CodeIgniter te dan una fachada o factoría, un helper de respuesta HTTP y una vía de generación en cola o asíncrona, sobre el mismo motor.
  • Un puente sigue a tu framework, no a tu documento. Cambia cómo llamas al motor, nunca lo que el motor puede producir.
  • La vía autónoma siempre está disponible. Una herramienta de CLI, un demonio o una biblioteca no tienen ningún framework desde el que tender un puente; construyen un documento directamente.
  • Un único modelo de documento viaja por los cuatro. Los mismos objetos de valor, enumeraciones y contrato de salida aparecen en todas partes, de modo que un documento se mueve entre lugares de llamada sin cambios.

La arquitectura es una división deliberada. El motor es el activo; el puente es un adaptador fino que habla los modismos de un framework. Un puente registra un pequeño espacio de nombres sobre el núcleo compartido mediante la autocarga estándar (Spec: PSR-4 Autoloader, §3) y devuelve un documento a través del contrato de contenedor (Spec: PSR-11 Container, §1.1.2). Ese contrato es el héroe silencioso aquí: permite que dos resoluciones del mismo identificador devuelvan instancias distintas, que es exactamente cómo un puente te da un documento nuevo y desechable por petición a la vez que mantiene el registro de fuentes analizadas y la caché de imágenes como singletons de proceso. Los workers de larga vida —Octane, RoadRunner, Swoole, Messenger— obtienen un análisis de fuentes amortizado sin fuga de estado entre peticiones, por construcción.

Los cuatro modismos difieren solo en la superficie:

  1. Core enginenextpdf/core — the framework-agnostic PDF 2.0 engine; the single shared document model, value objects, and output contract.
  2. Laravel bridgenextpdf/laravel — auto-discovered provider, a Pdf facade, a PdfResponse helper, and a queued GeneratePdfJob.
  3. Symfony bridgenextpdf/symfony — an auto-registered bundle, an injectable PdfFactory, a PdfResponse, and an optional Messenger handler.
  4. CodeIgniter bridgenextpdf/codeigniter — a service and pdf() helper, a Pdf library over a disposable Document, and a PdfResponse.
  5. StandaloneNo framework to bridge from — construct a Document directly in a CLI tool, daemon, or library.
One framework-agnostic core engine reached through four idiomatic surfaces: a Laravel facade, an injected Symfony factory, a CodeIgniter service, or a directly constructed standalone document — each handing back the same disposable Document model.

Lee el diagrama de izquierda a derecha y la lección es la simetría. Cada superficie resuelve al mismo Document. La fachada de Laravel, la factoría de Symfony, el servicio de CodeIgniter y el constructor autónomo son cuatro puertas a una misma sala.

Las mismas tres líneas de intención, expresadas en cada modismo. El cuerpo que construye el documento —páginas, fuentes, celdas, firma, conformidad— es idéntico en los cuatro, porque es el mismo motor.

<?php
declare(strict_types=1);
// Laravel — resolve a fresh document from the container.
use NextPDF\Contracts\PdfDocumentInterface;
$document = app(PdfDocumentInterface::class);
// Symfony — inject the factory, then ask it for a document.
use NextPDF\Symfony\Service\PdfFactory;
$document = $factory->create(); // PdfFactory injected into your service
// CodeIgniter — pull it from the Services layer.
use NextPDF\CodeIgniter\Config\Services;
$document = Services::pdfDocument();
// Standalone — no framework; construct it directly.
use NextPDF\Core\Document;
$document = Document::createStandalone();
// From here, the code is identical regardless of how $document arrived.
$document->addPage();
$document->cell(0, 10, 'One engine, every framework', newLine: true);
$bytes = $document->getPdfData();

Las primeras líneas son la única diferencia. Todo lo posterior es portable: mueve un servicio de construcción de documentos de Symfony a un worker autónomo y el código de renderizado no cambia, porque el contrato del que depende no cambió.

La suposición frecuente es que el puente de framework desbloquea capacidades: que la validación de firma de largo plazo o la facturación electrónica estructurada llegan porque instalaste nextpdf/laravel en vez de llamar al motor directamente. No es así. Un puente cambia el lugar de la llamada, nunca el alcance del motor. Las capacidades del núcleo, como la salida PDF/A y la firma PAdES de base, son de código abierto y llegan a cada superficie; las capacidades avanzadas las desbloquea una edición y entonces quedan disponibles a través de cualquier puente o de la vía autónoma por igual. Elegir una integración de framework no es elegir un conjunto de funciones.

La idea equivocada complementaria es que «un motor» tiene que significar una sola vía de renderizado para cada documento. No es así. El motor en proceso renderiza PDF directamente; cuando un documento necesita de verdad un motor de maquetación de nivel navegador, un paquete de renderizado se encarga de eso. Renderizado e invocación son ejes separados: la guía de decisión de integración es el lugar que los mapea.

Un puente no amplía lo que el motor puede renderizar. Ese es el límite honesto, y es el punto: la capacidad reside en el núcleo y en el nivel, no en el adaptador a través del que lo alcanzas.

Framework bridges over one engine — edition availability
EditionAvailability
Core

Cada puente (Laravel, Symfony, CodeIgniter) y la vía autónoma son Apache-2.0 y funcionan sobre Core. Adaptan o exponen el motor; no restringen funciones ni cambian lo que puede producir.

Pro

Las capacidades avanzadas, como la validación de firma de largo plazo (PAdES B-LT y B-LTA), las desbloquea una edición y luego se alcanzan de forma idéntica a través de cualquier puente o de la vía autónoma, nunca cambiando de framework. La salida PDF/A de archivado y la firma PAdES de base (B-B y B-T) ya están en Core, disponibles de la misma forma a través de cada superficie.

Enterprise

La facturación electrónica estructurada (EN 16931) y las herramientas de cumplimiento más profundas son también capacidades de edición, igualmente las mismas sea cual sea la superficie que llame al motor, mientras que la propia validación de conformidad se incluye en Core.

Conviene enunciar con claridad dos fronteras más. Primera, cada puente sigue una versión mayor actual de su framework —Laravel, Symfony y CodeIgniter fijan cada uno un rango soportado—, de modo que «todos los frameworks» significa la versión soportada de cada uno, no toda versión histórica; trata la propia documentación de cada paquete como autoridad para su API. Segunda, los puentes son adaptadores de framework, no backends de renderizado. Si un documento necesita un motor completo de maquetación de navegador, esa es una elección de renderizado independiente de qué framework llamó al motor.

  • La guía de decisión de integración — el mapa de caso de uso a paquete, incluidos los renderizadores y la superficie del servicio Connect, cuando necesitas decidir en vez de estandarizar.
  • Núcleo abierto, sin cautiverio — por qué el motor es el activo y los puentes son finos, de modo que estandarizar no te atrapa.
  • El pipeline HTML — qué cubre el motor en proceso, para que sepas cuándo un renderizador de navegador es la cuestión aparte.
  • Las bases de PHP 8.4 — el suelo de runtime que comparten cada puente y la vía autónoma.
  • Motor del núcleonextpdf/core, el motor PDF 2.0 agnóstico al framework sobre el que construyen cada puente y la vía autónoma.
  • Puente de framework — un paquete de integración (Laravel, Symfony, CodeIgniter) que adapta el motor a los modismos de un framework —fachada, factoría, respuesta, trabajo en cola— sin cambiar sus capacidades.
  • Vía autónoma — usar el motor del núcleo directamente, sin framework, construyendo tú mismo un Document; la ruta para herramientas de CLI, demonios y bibliotecas.
  • Documento desechable — el contrato Document de un solo uso: construir, emitir, descartar. Cada resolución de contenedor devuelve uno nuevo, de modo que no se fuga estado entre peticiones en un worker de larga vida.
  • PAdES — PDF Advanced Electronic Signatures, la familia de perfiles ETSI para firma de PDF. La firma de base (B-B y B-T) está en Core; la validación de largo plazo (B-LT y B-LTA) es una capacidad de edición avanzada. Cualquiera de ellas se alcanza a través de cualquier superficie, tratada en profundidad en las páginas de firma.