Core / trait HasOutput
De un vistazo
Sección titulada «De un vistazo»HasOutput es el trait del concern encargado de serializar el documento. Proporciona output(), save() y getPdfData(), junto con accesores a los motores internos.
Instalación
Sección titulada «Instalación»composer require nextpdf/core:^3Panorama conceptual
Sección titulada «Panorama conceptual»trait HasOutput (src/Core/Concerns/HasOutput.php, desde 1.2.0) se integra en Document. Se encarga del paso final: convertir el modelo en memoria en bytes de PDF y entregarlos.
output(?string $filename = null, OutputDestination $dest = OutputDestination::Inline): string construye el PDF y lo entrega. OutputDestination es un enum respaldado por cadenas con cuatro casos: Inline ('I'), Download ('D'), File ('F') y String ('S'). Inline establece Content-Type: application/pdf con una disposición en línea. Download envía una disposición de adjunto. File escribe en $filename y lanza InvalidConfigException cuando $filename es null. String devuelve los bytes sin enviar encabezados. En todos los casos, el método devuelve el binario PDF en bruto.
save(string $path): void construye el PDF y lo escribe en un archivo. Rechaza los envoltorios de flujo y los bytes nulos en la ruta. Resuelve el directorio padre con realpath() para impedir el recorrido de rutas. Luego escribe mediante AtomicFileWriter. Un lector concurrente verá el archivo anterior o los bytes nuevos, nunca una escritura parcial. getPdfData(): string construye y devuelve los bytes, y deja la entrega a cargo de quien lo invoca.
El paso de construcción es interno. buildPdf() bloquea las banderas experimentales, vuelca la página activa, reemplaza el alias del recuento total de páginas en cada flujo de contenido de página y serializa mediante PdfWriter. Cada página se convierte en uno o más flujos de contenido (ISO 32000-2:2020 §7.8.2). El árbol de páginas emitido por el writer mantiene Count coherente con Kids (§7.7.3).
El trait también expone accesores a motores: getFontRegistry(), getWriter(), getDrawingEngine(), getTransformEngine(), getTextRenderer(), getHeaderFooter(), getBookmarkManager() y getLinkManager(). Los accesores diferidos a motores —getFormFieldManager(), getLayerManager(), getTemplateManager(), getFileAttachment(), getJavaScriptManager()— devuelven null hasta que la función se usa por primera vez.
Superficie de la API
Sección titulada «Superficie de la API»| Símbolo | Tipo | Estabilidad | Desde |
|---|---|---|---|
output(?string, OutputDestination): string | método | estable | 1.2.0 |
save(string $path): void | método | estable | 1.2.0 |
getPdfData(): string | método | estable | 1.2.0 |
getFontRegistry(): FontRegistryInterface | método | estable | 1.2.0 |
getWriter(): PdfWriter | método | estable | 1.2.0 |
getDrawingEngine(): DrawingEngine | método | estable | 1.2.0 |
getFormFieldManager(): ?FormFieldManager | método | estable | 1.2.0 |
getLayerManager(): ?LayerManager | método | estable | 1.2.0 |
enableV2ContentStream(bool): static | método | obsoleto (1.12.0) | 1.2.0 |
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');
echo "Created: output/01-hello-world.pdf\n";Fuente: derivado de examples/01-hello-world.php.
Ejemplo de código — Producción
Sección titulada «Ejemplo de código — Producción»getPdfData() devuelve los bytes para que un controlador los transmita, de modo que el framework controle la respuesta HTTP.
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\Document;
function buildInvoicePdf(string $invoiceNo): string{ $doc = Document::createStandalone(); $doc->setTitle("Invoice {$invoiceNo}"); $doc->addPage(); $doc->setFont('helvetica', 'B', 18); $doc->cell(0, 12, "Invoice {$invoiceNo}", newLine: true);
return $doc->getPdfData();}
// In a PSR-7 controller:// return $response// ->withHeader('Content-Type', 'application/pdf')// ->withBody($streamFactory->createStream(buildInvoicePdf('001')));Fuente: patrón tomado de examples/02-pdf-factory.php.
Casos límite y trampas
Sección titulada «Casos límite y trampas»output()conOutputDestination::FilelanzaInvalidConfigExceptioncuando$filenamees null.output()omite la emisión de encabezados cuandoheaders_sent()devuelve true, así que se mantiene seguro tras una salida parcial.save()rechaza cualquier ruta con un prefijo de envoltorio de flujo (scheme://) o un byte nulo.save()requiere que el directorio padre exista. Un directorio que no se puede resolver lanzaInvalidConfigException.enableV2ContentStream()está obsoleto desde 1.12.0. La bandera se ignora; se debe eliminar la llamada.- Los accesores de motores diferidos devuelven
nullantes del primer uso de la función. Debe comprobarse si es null antes de desreferenciar.
Rendimiento
Sección titulada «Rendimiento»buildPdf() serializa una única vez en O(total de bytes de contenido). No realiza una segunda pasada sobre un árbol retenido (ADR-001). save() añade un único renombrado atómico. La salida es determinista byte a byte con DeterministicSettings. DeterministicSettings admite el perfil de reproducibilidad a nivel de bits. Presupuesto: 1500 ms / 64 MB para el inicio rápido canónico.
Notas de seguridad
Sección titulada «Notas de seguridad»save() bloquea el recorrido de rutas y los envoltorios de flujo, y luego escribe de forma atómica mediante AtomicFileWriter. Esto cierra la ventana TOCTOU del archivo producido. output() sanea el nombre de archivo en el encabezado Content-Disposition. Las advertencias se escriben en un archivo lateral junto al PDF y se envían a stderr; nunca se insertan en línea dentro de los bytes del PDF.
Conformidad
Sección titulada «Conformidad»| Afirmación | Fuente | Cláusula | reference_id |
|---|---|---|---|
| Cada página se serializa como uno o más flujos de contenido | ISO 32000-2:2020 | §7.8.2 | |
Count se escribe de forma coherente con Kids en el arreglo | ISO 32000-2:2020 | §7.7.3 |
Las cláusulas están parafraseadas. No se reproduce ningún texto normativo.
Véase también
Sección titulada «Véase también»/modules/core/core/document-facade/— la fachada que componeHasOutput/modules/core/core/— panorama de Core y el modelo de traits de concern/modules/core/writer/— writer mediante el cual serializaPdfWriterbuildPdf()/modules/core/core/has-security/—HasSecurity: cifrado aplicado antes de la serialización/modules/core/core/has-pages/—HasPages:flushCurrentPage()invocado porbuildPdf()/modules/core/contracts/— enumOutputDestinationusado poroutput()/modules/core/exception/—InvalidConfigExceptioncuandoFilerecibe un nombre de archivo null o una ruta incorrecta <!— evidence: src/Core/Concerns/HasOutput.php (trait HasOutput @since 1.2.0; output(?string=null,OutputDestination=Inline):string — File throws InvalidConfigException when filename null, Inline/Download set Content-Type+Content-Disposition guarded by !headers_sent(), sanitizeHeaderFilename; save(string):void — rejects \0 + ^[a-z]+:// stream wrappers, realpath parent dir, AtomicFileWriter::write, writeWarningSidecar; getPdfData():string; buildPdf() lockExperimentalFlags+flushCurrentPage+NB_PAGES_ALIAS replace; getFontRegistry/getWriter/getDrawingEngine/getTransformEngine/getTextRenderer/getHeaderFooter/getBookmarkManager/getLinkManager; getFormFieldManager/getLayerManager/getTemplateManager/getFileAttachment/getJavaScriptManager nullable; enableV2ContentStream @deprecated 1.12.0 ignored); src/Contracts/OutputDestination.php (enum:string Inline=I/Download=D/File=F/String=S); src/Core/DeterministicSettings.php; ADR-001; examples/01-hello-world.php, examples/02-pdf-factory.php. RAG iso32000_2_sec7 §7.8.2 , §7.7.3 >