如何在Laravel应用中生成并导出PDF文件?求实现示例
Laravel生成并导出PDF的推荐方案与实现示例
方案选择建议
- barryvdh/laravel-dompdf:适合大多数常规场景,无需额外系统依赖,与Blade视图无缝集成,学习成本低,能满足发票、收据这类布局不复杂的PDF生成需求。
- barryvdh/laravel-snappy:依赖wkhtmltopdf(需单独安装系统级依赖),支持复杂CSS3、JavaScript渲染和精确的分页/页眉页脚控制,适合对PDF格式精度要求极高的场景。
基于dompdf的实现示例(预约关联支付的发票场景)
1. 安装扩展包
composer require barryvdh/laravel-dompdf
(可选)发布配置文件,用于自定义PDF的纸张大小、编码等设置:
php artisan vendor:publish --provider="Barryvdh\DomPDF\ServiceProvider"
2. 构建控制器逻辑
创建InvoiceController.php,实现PDF生成、下载、服务器存储的核心逻辑:
<?php namespace App\Http\Controllers; use App\Models\Appointment; use Barryvdh\DomPDF\Facade\Pdf; use Illuminate\Support\Facades\Storage; class InvoiceController extends Controller { public function generateInvoice($appointmentId) { // 获取预约及关联的支付数据(需确保Appointment模型已定义payment关联) $appointment = Appointment::with('payment')->findOrFail($appointmentId); // 加载Blade视图并生成PDF $pdf = Pdf::loadView('invoices.receipt', compact('appointment')); // 选项1:直接在浏览器下载PDF return $pdf->download("invoice-{$appointment->id}.pdf"); // 选项2:将PDF存储到服务器(示例存储在storage/app/public/invoices目录) // $storagePath = "invoices/invoice-{$appointment->id}.pdf"; // Storage::put($storagePath, $pdf->output()); // return response()->download(storage_path("app/public/{$storagePath}")); } }
3. 创建Blade发票模板
在resources/views/invoices/receipt.blade.php编写发票HTML结构,直接调用关联数据:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>发票 #{{ $appointment->id }}</title> <style> body { font-family: Arial, sans-serif; padding: 20px; } .invoice-header { text-align: center; border-bottom: 1px solid #ddd; padding-bottom: 15px; } .invoice-info { margin: 20px 0; display: flex; justify-content: space-between; } .table { width: 100%; border-collapse: collapse; margin-top: 30px; } .table th, .table td { border: 1px solid #ddd; padding: 10px; text-align: left; } .table th { background-color: #f5f5f5; } .footer { margin-top: 40px; text-align: right; color: #666; } </style> </head> <body> <div class="invoice-header"> <h1>服务收据</h1> <p>预约编号:{{ $appointment->id }}</p> </div> <div class="invoice-info"> <div> <p><strong>客户姓名:</strong> {{ $appointment->client_name }}</p> <p><strong>预约日期:</strong> {{ $appointment->appointment_date->format('Y-m-d H:i') }}</p> </div> <div> <p><strong>支付状态:</strong> {{ $appointment->payment->status == 'paid' ? '已支付' : '未支付' }}</p> <p><strong>支付时间:</strong> {{ $appointment->payment->paid_at?->format('Y-m-d H:i') }}</p> </div> </div> <table class="table"> <thead> <tr> <th>服务项目</th> <th>金额(元)</th> <th>支付描述</th> </tr> </thead> <tbody> <tr> <td>{{ $appointment->service_name }}</td> <td>{{ number_format($appointment->payment->amount, 2) }}</td> <td>{{ $appointment->payment->payment_description }}</td> </tr> </tbody> </table> <div class="footer"> <p>感谢您的惠顾!</p> </div> </body> </html>
4. 配置路由
在routes/web.php添加生成发票的路由:
use App\Http\Controllers\InvoiceController; Route::get('/invoice/{appointmentId}', [InvoiceController::class, 'generateInvoice'])->name('invoice.generate');
基于Snappy的快速说明
如果需要复杂的PDF渲染(如精确分页、页眉页脚、JS交互),可选择Snappy:
- 安装扩展包:
composer require barryvdh/laravel-snappy - 安装wkhtmltopdf系统依赖(根据操作系统下载对应版本并配置路径)
- 控制器逻辑与dompdf基本一致,仅需替换Facade:
use Barryvdh\Snappy\Facades\SnappyPdf; // 生成PDF $pdf = SnappyPdf::loadView('invoices.receipt', compact('appointment')); // 下载或存储逻辑与dompdf完全相同
内容的提问来源于stack exchange,提问作者nflux
相关产品推荐
相关产品推荐

