Contracts: 41 interfaces públicas (SPI)
Un vistazo general
Sección titulada «Un vistazo general»NextPDF\Contracts es la interfaz pública de proveedor de servicios (SPI): 41 interfaces y enums dentro de src/Contracts/ con una etiqueta @stability explícita y una promesa de compatibilidad con versiones anteriores. Los paquetes de extensión, los puentes de framework y las ediciones Pro y Enterprise programan contra estos tipos, nunca contra clases concretas.
Instalación
Sección titulada «Instalación»composer require nextpdf/core:^3Panorama conceptual
Sección titulada «Panorama conceptual»El motor separa dos superficies. Las clases concretas dentro de src/Core/, src/Html/ y src/Writer/ no tienen ninguna promesa de compatibilidad. Pueden cambiar libremente entre versiones menores. El espacio de nombres Contracts funciona de manera opuesta: es un conjunto curado de tipos cuyas firmas quedan congeladas según el nivel de estabilidad que declaran. Todo lo externo al motor depende de este espacio de nombres y de nada más profundo. Esto incluye los puentes de Laravel, Symfony y CodeIgniter, el shim compat-tcpdf, NextPDF Server y las ediciones Pro y Enterprise.
Cada contrato declara en su PHPDoc uno de cuatro niveles. Un contrato stable no admite cambios incompatibles en una versión menor o de parche. Los métodos nuevos llegan únicamente con implementaciones predeterminadas. Un contrato experimental puede cambiar en una versión menor con un aviso de obsolescencia. Un contrato deprecated identifica su reemplazo. Un número reducido son solo de contrato, como StreamingWriterInterface y CursorInterface: el tipo se publica y se congela, pero todavía no se distribuye ninguna implementación de producción.
La lista autoritativa de niveles es docs/extension-points.json (versión del manifiesto 3.0.0, 67 puntos publicados entre Contracts y Event). Una prueba verificable por máquina, tests/Unit/Contracts/StabilityContractTest.php, lee ese manifiesto. La compilación falla bajo cinco condiciones: un tipo listado que falta, una clase reflejada que no coincide con el manifiesto, una etiqueta PHPDoc @stability que se desvía del manifiesto, un contrato dentro de src/Contracts/ que está ausente del manifiesto o un tipo @internal que se filtra en él. La superficie de contratos no puede desviarse sin que se detecte.
Los contratos se reparten en nueve dominios. Cada uno tiene una página dedicada: construcción de documentos, firma, codificación de códigos de barras, tipografía, política de seguridad, extracción, observabilidad y streaming. La división refleja cómo un integrador adopta el motor. Se depende del contrato de documento para generar PDF, de los contratos de firma para añadir una firma y de los contratos de política de seguridad para restringir el HTML no confiable.
La resolución de una implementación opcional sigue un único patrón en todo el motor. El core comprueba si existe una clase concreta con class_exists() y la adapta al contrato. LtvManagerInterface y PdfAManagerInterface resuelven sus implementaciones Pro de esta manera. Por eso el core se mantiene como Apache-2.0 sin ninguna dependencia obligatoria de código comercial.
Superficie de la API
Sección titulada «Superficie de la API»| Contract | Tipo | Estabilidad | Desde | Dominio |
|---|---|---|---|---|
PdfDocumentInterface | interface | stable | 1.0.0 | document |
DocumentFactoryInterface | interface | stable | 1.7.0 | document |
ResettableService | interface | stable | 1.7.0 | document |
OutputDestination | enum | stable | 1.0.0 | document |
Orientation | enum | stable | 1.0.0 | document |
Alignment | enum | stable | 1.0.0 | document |
SignerInterface | interface | stable | 1.0.0 | signing |
HsmSignerInterface | interface | stable | 1.0.0 | signing |
DeferredSignerInterface | interface | experimental | 3.0.0 | signing |
TimestampProviderInterface | interface | experimental | 3.0.0 | signing |
LtvManagerInterface | interface | stable | 1.10.0 | signing |
CryptoPolicyInterface | interface | stable | 1.9.0 | signing |
Barcode1DEncoderInterface | interface | stable | 1.0.0 | barcode |
Barcode2DEncoderInterface | interface | stable | 1.0.0 | barcode |
BarcodeEncoderInterface | interface | stable | 3.0.0 | barcode |
Gs1DataParserInterface | interface | stable | 1.0.0 | barcode |
FontRegistryInterface | interface | stable | 1.7.0 | typography |
TextPreprocessorInterface | interface | stable | 1.9.0 | typography |
HtmlSecurityPolicyInterface | interface | stable | 3.1.0 | security-policy |
ExternalResourcePolicyInterface | interface | stable | 4.0.0 | security-policy |
InspectorInterface | interface | experimental | 2.2.0 | extraction |
EmbeddingServiceInterface | interface | experimental | 2.1.0 | extraction |
VectorIndexInterface | interface | experimental | 2.1.0 | extraction |
JobNotificationInterface | interface | experimental | 2.2.0 | observability |
SpectrumInterface | interface | experimental | 2.1.0 | observability |
StreamingWriterInterface | interface | experimental | 3.1.0 | streaming |
CursorInterface | interface | experimental | 3.1.0 | streaming |
La tabla enumera los contratos principales. Los tipos restantes —DTO de objetos de valor (TextSegment, TextPreprocessResult), el subespacio de nombres EInvoice, enums de comportamiento (DegradationPolicy, UnderlineStyle) y contratos de importación (ImportedFormObjectInterface, EmbeddedPdfObjectInterface, ChromeRenderResultInterface)— se documentan en las páginas de dominio bajo Véase también. La lista completa, legible por máquina, es docs/extension-points.json, replicada en .ai/contracts-map.md.
Ejemplo de código — Inicio rápido
Sección titulada «Ejemplo de código — Inicio rápido»<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->setTitle('Hello World');$doc->addPage();$doc->setFont('helvetica', '', 24);$doc->cell(0, 15, 'Hello, NextPDF!', newLine: true);$doc->save(__DIR__ . '/output/01-hello-world.pdf');Document::createStandalone() devuelve un Document concreto que satisface PdfDocumentInterface. Conviene usar el type-hint de la interfaz en los servicios propios para que los componentes internos del motor sigan siendo intercambiables.
Ejemplo de código — Producción
Sección titulada «Ejemplo de código — Producción»<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\DocumentFactory;use NextPDF\Core\PdfFactory;use NextPDF\Graphics\ImageRegistry;use NextPDF\Typography\FontRegistry;
// Created once at process boot in a RoadRunner/Swoole/Octane worker.$fontRegistry = new FontRegistry();$imageRegistry = new ImageRegistry(maxCacheBytes: 50 * 1024 * 1024);$documentFactory = new DocumentFactory($fontRegistry, $imageRegistry);
$factory = PdfFactory::new() ->withCompress(true) ->withDocumentFactory($documentFactory);
for ($request = 1; $request <= 3; $request++) { $doc = $factory->create(); $doc->setTitle("Worker Request #{$request}"); $doc->addPage(); $doc->setFont('helvetica', 'B', 16); $doc->cell(0, 12, "Worker Request #{$request}", newLine: true); $doc->save(__DIR__ . "/output/14-worker-request-{$request}.pdf");}DocumentFactory implementa DocumentFactoryInterface. Mantiene singletons de FontRegistryInterface y ImageRegistryInterface con tiempo de vida de proceso y los inyecta en cada Document desechable, de modo que un worker analiza cada fuente una sola vez a lo largo de miles de solicitudes.
Casos límite y trampas
Sección titulada «Casos límite y trampas»- Un tipo solo de contrato compila, pero no tiene respaldo en tiempo de ejecución. Un
newcontraStreamingWriterInterfaceoCursorInterfaceno puede tener éxito porque todavía no hay ninguna clase que los implemente. Deben tratarse como una API declarada de forma anticipada. - La etiqueta PHPDoc
@stabilityes la fuente de verdad para un tipo individual.docs/extension-points.jsones la fuente de verdad para el conjunto. Cuando no concuerdan,StabilityContractTestfalla; no se debe ocultar la discrepancia editando uno de los dos lados. experimentalno significa inestable en la práctica; significa que la promesa de compatibilidad es más débil. Se debe leer el campobc_promisede cada contrato en.ai/contracts-map.mdantes de fijarse a él.- Una clase
@internalnunca es un contrato, aunque otros paquetes técnicamente puedan referenciarla. La prueba de estabilidad rechaza cualquier tipo@internalque aparezca en el manifiesto. - Añadir un método a una interfaz
stablees un cambio incompatible para quienes la implementan, salvo que el método se distribuya con una implementación predeterminada. El motor añade capacidades mediante interfaces nuevas, no ampliando las existentes.
Rendimiento
Sección titulada «Rendimiento»Programar contra Contracts no añade ningún costo medible en tiempo de ejecución: un type-hint de interfaz se resuelve en el momento del enlace, no en cada llamada. El performance_budget para el ejemplo de worker de esta página es de 1500 ms de tiempo de pared y 64 MB de pico a lo largo de tres documentos. El análisis de fuentes en la primera solicitud domina ese presupuesto. Las solicitudes posteriores reutilizan la caché del registro y reducen a milisegundos de un solo dígito el trabajo atribuible a los contratos. El modelo de costo es O(1) por despacho de contrato; el trabajo está en la implementación concreta, documentada en cada página de dominio.
Notas de seguridad
Sección titulada «Notas de seguridad»La SPI también es un límite de seguridad. HtmlSecurityPolicyInterface y ExternalResourcePolicyInterface son contratos de denegación predeterminada que restringen lo que el HTML no confiable puede hacer antes de llegar a un renderer. CryptoPolicyInterface controla la selección de algoritmo y la robustez de clave para la firma y el cifrado. Como son contratos, un integrador puede proporcionar una política más estricta sin bifurcar el motor. Conviene fijarse en el nivel stable para cualquier política relevante para la seguridad. Los contratos de política experimentales pueden cambiar de forma entre versiones menores. Las páginas de dominio de firma y de política de seguridad incluyen el modelo de amenazas completo y las referencias normativas.
Conformidad
Sección titulada «Conformidad»Este panorama no hace ninguna afirmación normativa directa; cada página de dominio renderiza su propio bloque de citations. Los contratos de firma se corresponden con ISO 32000-2 §12.8 (firmas digitales) y ETSI EN 319 142 (líneas base PAdES). El gestor de PDF/A se corresponde con ISO 19005-4. Consultar las páginas de firma, política de seguridad y extracción para ver las tablas de conformidad a nivel de cláusula.
Contexto comercial
Sección titulada «Contexto comercial»Las ediciones Pro y Enterprise implementan el código de producción detrás de varios contratos del core: LtvManagerInterface (validación a largo plazo), PdfAManagerInterface (cumplimiento de PDF/A), los firmantes con módulo de seguridad de hardware (HSM) y diferidos, los codificadores de códigos de barras y los contratos de embedding y de índice vectorial. El core publica y congela la interfaz; el paquete Premium distribuye la implementación. Esto mantiene el motor de código abierto bajo Apache-2.0 y, a la vez, ofrece a los despliegues comerciales una actualización directa (drop-in) sin cambios en la API.
Véase también
Sección titulada «Véase también»- Contracts / Document — contratos de documento PDF, factory y registro.
- Contracts / Signing — contratos de firmante, HSM, marca de tiempo y LTV.
- Contracts / Security Policy — contratos de política criptográfica, de HTML y de recursos.
- Contracts / Typography — contratos de registro de fuentes y de preprocesamiento de texto.
- Contracts / Extraction — contratos de inspector, PDF/A, embedding y factura electrónica.
- Core — clases concretas que satisfacen estos contratos.
- Event — contraparte del SPI de eventos, publicada junto a
Contracts.