队列任务
GeneratePdfJob 提供开箱即用的队列式 PDF 生成功能。对于耗时的文件,将工作交给后台工作者可以避免阻塞 HTTP 请求。
php
use Yeeefang\TcpdfNext\Laravel\Jobs\GeneratePdfJob;派发任务
创建任务时传入一个闭包,该闭包接收 Document 实例并定义 PDF 的内容:
php
use Yeeefang\TcpdfNext\Laravel\Jobs\GeneratePdfJob;
GeneratePdfJob::dispatch(
builder: function ($pdf) use ($report) {
$pdf->setTitle($report->title)
->addPage()
->setFont('Helvetica', 'B', 16)
->cell(0, 10, $report->title)
->setFont('Helvetica', '', 11)
->multiCell(0, 6, $report->body);
},
outputPath: storage_path("app/reports/{$report->id}.pdf"),
);成功与失败回调
通过 onSuccess 和 onFailure 回调处理任务完成后的逻辑:
php
GeneratePdfJob::dispatch(
builder: function ($pdf) use ($invoice) {
$pdf->setTitle("发票 #{$invoice->number}")
->addPage()
->setFont('Helvetica', '', 12)
->cell(0, 10, "发票 #{$invoice->number}");
},
outputPath: storage_path("app/invoices/{$invoice->id}.pdf"),
onSuccess: function (string $path) use ($invoice) {
$invoice->update(['pdf_path' => $path, 'status' => 'ready']);
Mail::to($invoice->customer)->send(new InvoiceReady($invoice));
},
onFailure: function (\Throwable $e) use ($invoice) {
$invoice->update(['status' => 'generation_failed']);
Log::error('PDF 生成失败', [
'invoice' => $invoice->id,
'error' => $e->getMessage(),
]);
},
);队列配置
指定队列名称、连接与延迟:
php
GeneratePdfJob::dispatch(
builder: $builder,
outputPath: $path,
)->onQueue('pdf-generation')
->onConnection('redis')
->delay(now()->addMinutes(5));重试与超时
在 config/tcpdf-next.php 中设置默认值,或在派发时覆盖:
php
// config/tcpdf-next.php
'queue' => [
'connection' => env('TCPDF_QUEUE_CONNECTION', 'redis'),
'name' => env('TCPDF_QUEUE_NAME', 'pdf-generation'),
'tries' => 3,
'timeout' => 120,
'backoff' => [10, 30, 60],
],任务会使用指数退避策略:第一次重试等待 10 秒、第二次 30 秒、第三次 60 秒。
批量处理
使用 Laravel 的 Bus::batch() 同时生成多份 PDF:
php
use Illuminate\Support\Facades\Bus;
use Yeeefang\TcpdfNext\Laravel\Jobs\GeneratePdfJob;
$jobs = $invoices->map(fn (Invoice $invoice) => new GeneratePdfJob(
builder: function ($pdf) use ($invoice) {
$pdf->setTitle("发票 #{$invoice->number}")
->addPage()
->setFont('Helvetica', '', 12)
->cell(0, 10, "发票 #{$invoice->number}");
},
outputPath: storage_path("app/invoices/{$invoice->id}.pdf"),
));
Bus::batch($jobs)
->name('批量发票生成')
->onQueue('pdf-generation')
->allowFailures()
->then(function () {
Log::info('所有发票 PDF 已生成完毕');
})
->catch(function (\Throwable $e) {
Log::error('部分发票生成失败', ['error' => $e->getMessage()]);
})
->finally(function () {
// 无论成败皆执行
Notification::send($admins, new BatchCompleteNotification());
})
->dispatch();搭配 Blade 视图
结合 Blade 模板生成更复杂的 PDF:
php
GeneratePdfJob::dispatch(
builder: function ($pdf) use ($order) {
$html = view('pdf.order-confirmation', [
'order' => $order,
'items' => $order->items,
])->render();
$pdf->setTitle("订单确认 #{$order->id}")
->writeHtml($html);
},
outputPath: storage_path("app/orders/{$order->id}.pdf"),
);监控任务
使用 Laravel Horizon 或内置的 queue:monitor 指令追踪 PDF 队列状态:
bash
php artisan queue:monitor pdf-generation --max=100下一步
- HTTP 响应 — 同步传递 PDF 至浏览器
- Pdf 门面 — 文件创建与测试辅助
- Laravel 配置 — 队列相关配置选项