Ir al contenido

Guía para desarrolladores de Laravel

El paquete de Laravel adapta NextPDF a las convenciones de Laravel sin alterar el ciclo de vida del documento del núcleo. El contenedor gestiona los registros y las factorías compartidos. Cada documento PDF es desechable y debe construirse, devolverse, transmitirse o guardarse una sola vez.

Usar esta guía al diseñar servicios de aplicación, jobs en cola, flujos de respuesta o cobertura de pruebas en torno a nextpdf/laravel.

CapaPropiedadResponsabilidadNo incluir aquí
ControladorAplicaciónAutorizar la solicitud, elegir un constructor de documentos y devolver una respuesta.Reglas de diseño del PDF compartidas entre casos de uso.
Servicio de aplicaciónAplicaciónRecopilar los datos de dominio y llamar al código de construcción de documentos.Lógica de arranque del contenedor o configuración del paquete.
Constructor de documentosAplicaciónTraducir los datos de dominio en llamadas al documento de NextPDF.Objetos de solicitud, lógica de consultas de Eloquent o detalles del transporte de cola.
Integración con Laravelnextpdf/laravelVincular las factorías, los registros, el firmante, el cliente TSA, la facade, las respuestas y el job en cola.Rutas de almacenamiento específicas del negocio o políticas de inquilinos.
Motor del núcleonextpdf/nextpdfConstruir y serializar el PDF.Política de respuesta, cola o sistema de archivos de Laravel.
EtapaComportamientoAcción del desarrollador
Registro del proveedor de serviciosNextPdfServiceProvider::register() registra los registros compartidos, la factoría de documentos, el binding del documento, el cliente HTTP, el cliente TSA, el firmante y los contratos opcionales de facturación electrónica.Publicar y revisar config/nextpdf.php antes de pasar a producción.
Resolución del documentoLa facade Pdf y el binding PdfDocumentInterface resuelven un documento nuevo mediante DocumentFactoryInterface.Resolver un documento una sola vez por solicitud, comando o job en cola.
CreaciónEl código de la aplicación llama a las API del documento del núcleo a través de la facade o del documento inyectado.Mantener la extracción de datos de dominio fuera del constructor de documentos.
Salida terminalPdfResponse emite la salida HTTP, o el documento se guarda en disco.Elegir una sola ruta de salida terminal por documento.
Ejecución en colaGeneratePdfJob reconstruye el documento dentro del worker y vuelve a validar la ruta de salida.Pasar contexto escalar y mantener los callbacks idempotentes.
RutaPropósito
app/Pdf/Builders/*Constructores de documentos puros. Reciben datos y devuelven un documento completo.
app/Pdf/Data/*DTO pequeños que transportan datos de entrada del documento ya autorizados.
app/Services/*Orquestación de la aplicación, consultas, traspaso de la autorización y selección de la ruta de almacenamiento.
app/Jobs/*Envoltorios opcionales en torno a GeneratePdfJob cuando la aplicación necesita jobs con nombre.
tests/Feature/Pdf/*Pruebas de respuesta HTTP, despacho en cola y autorización.
tests/Unit/Pdf/*Pruebas de los constructores con datos de entrada pequeños y deterministas.

Mantener los constructores independientes de los objetos de solicitud de Laravel. Un constructor debe poder invocarse desde un controlador, un comando, una prueba y un worker de cola con la misma entrada.

<?php
namespace App\Pdf\Builders;
use App\Pdf\Data\InvoicePdfData;
use NextPDF\Contracts\PdfDocumentInterface;
final readonly class InvoicePdfBuilder
{
public function build(PdfDocumentInterface $pdf, InvoicePdfData $data): PdfDocumentInterface
{
$pdf->setTitle($data->title)
->addPage()
->setFont('dejavusans', '', 12)
->writeHtml($data->html);
return $pdf;
}
}

Usar la inyección por constructor cuando el flujo del PDF forme parte de la lógica de la aplicación. Usar la facade solo para flujos cortos de controlador donde el estilo estático mejore la legibilidad.

<?php
namespace App\Http\Controllers;
use App\Pdf\Builders\InvoicePdfBuilder;
use App\Pdf\Data\InvoicePdfData;
use NextPDF\Contracts\PdfDocumentInterface;
use NextPDF\Laravel\Http\PdfResponse;
final readonly class DownloadInvoiceController
{
public function __invoke(
PdfDocumentInterface $pdf,
InvoicePdfBuilder $builder,
) {
$document = $builder->build(
$pdf,
InvoicePdfData::fromInvoiceId(1234),
);
return PdfResponse::download($document, 'invoice-1234.pdf');
}
}

Los helpers de respuesta materializan los bytes del documento antes de construir la respuesta de Laravel. Son helpers de respuesta, no renderers en segundo plano.

GeneratePdfJob acepta un callable de construcción y una ruta de salida. El job valida las rutas inseguras durante la ejecución. Aun así, el código de la aplicación debe elegir una raíz de almacenamiento segura para el inquilino antes del despacho.

<?php
use App\Pdf\Builders\QueuedInvoiceBuilder;
use NextPDF\Laravel\Jobs\GeneratePdfJob;
GeneratePdfJob::dispatch(
outputPath: storage_path('app/pdfs/invoice-1234.pdf'),
builder: [QueuedInvoiceBuilder::class, 'build'],
)->onQueue(config('nextpdf.queue.queue', 'pdf'));

Los callbacks de cola deben ser pequeños. Es preferible escribir el estado duradero desde un listener de jobs de la aplicación, en lugar de almacenar closures complejas en el payload de la cola.

Punto de extensiónUsoRestricción
PdfDocumentInterface bindingReemplazar o decorar la creación de documentos para los valores predeterminados de toda la aplicación.Debe devolver una instancia de documento nueva.
DocumentFactoryInterfaceCrear explícitamente un documento nuevo en servicios y pruebas.No almacenar en caché los documentos devueltos.
config/nextpdf.phpValores predeterminados, ajustes de la cola, ajustes del renderer de Chrome, hooks de firma, TSA, caché de OCSP.Tratar las variables de entorno como configuración de despliegue, no como entrada de la solicitud.
GeneratePdfJob constructorConstruir documentos de forma asíncrona.El callable debe ser serializable por el transporte de cola de Laravel.
Callbacks de éxito/errorNotificación o limpieza posterior a la generación.Mantener los callbacks idempotentes y conscientes de los efectos secundarios.
Contratos opcionales de PremiumEmbebedor de facturas electrónicas, validador, perfil y ejecutor de Schematron.Resolverlos solo donde el paquete opcional esté instalado y con licencia.
  1. Construir el primer documento de forma síncrona en un controlador o una prueba de funcionalidad.
  2. Mover el código de diseño a una clase de constructor dentro de app/Pdf/Builders.
  3. Mover la lógica de consultas y autorización a un servicio de aplicación.
  4. Agregar pruebas de PdfResponse para las cabeceras y los nombres de archivo.
  5. Mover la generación lenta o de gran volumen a GeneratePdfJob.
  6. Agregar pruebas de cola para el contexto serializado, la política de ruta de salida y el manejo de errores.
  7. Medir la memoria y el tiempo de renderizado con datos de producción representativos.
ErrorDónde debe manejarseRespuesta recomendada
Solicitud no válida o documento no autorizadoControlador o política.Devolver la respuesta normal de autorización o validación de la aplicación.
Fuente faltante o imagen no válidaPruebas del constructor y registro de la aplicación.Hacer fallar la solicitud o el job; no emitir PDF parciales.
Ruta de salida inseguraServicio de almacenamiento de la aplicación y GeneratePdfJob.Rechazar antes del despacho y apoyarse en la validación del lado del worker como defensa en profundidad.
Error de firma o de TSALímite del servicio de firma.Decidir si el documento puede quedar sin firmar; de forma predeterminada, fallar de forma cerrada para los documentos regulados.
Tiempo de espera de la colaConfiguración del worker de la cola y observabilidad.Reintentar solo cuando el constructor sea determinista y la ruta de salida sea segura para sobrescribir.
AspectoPredeterminadoCuándo sobrescribir
Nombre de la colapdfUsar una cola dedicada cuando la generación compita con jobs de cara al usuario.
Tiempo de espera del job120 segundosAumentarlo solo después de medir el tamaño del documento y la capacidad del worker.
Nombre de archivo de la respuestadocument.pdfUsar identificadores de negocio saneados.
Registro de fuentesCompartido y bloqueado tras el calentamiento.Agregar preload_fonts para las fuentes usadas en rutas calientes.
Registro de imágenesCaché compartida y acotada.Reducir image_cache_mb para los workers con memoria limitada.
Fragmentación de la respuesta transmitidaFragmentos de 64 KB.No depender de los límites de los fragmentos; son un detalle de la salida.
  • Las pruebas del controlador verifican Content-Type, Content-Disposition y las cabeceras defensivas.
  • Las pruebas del constructor usan DTO deterministas y no consultan la base de datos.
  • Las pruebas de cola verifican que el constructor recibe un documento nuevo.
  • Las pruebas de rutas cubren el rechazo de traversal, stream-wrapper, byte nulo y rutas que no son .pdf.
  • Las pruebas del worker renderizan documentos representativos con el mismo límite de memoria que en producción.
  • Las pruebas de firma opcionales cubren el certificado faltante, la contraseña no válida, la TSA no disponible y el nivel de firma configurado.