本文目录导读:

这是一个很实用的需求,在PHP项目中实现多格式导出,核心思路通常是数据统一抽离 + 格式差异化处理。
我会为你梳理一个完整、可扩展的架构方案,并提供核心代码示例。
核心架构设计
- 数据层:从数据库或API查询原始数据,统一处理成数组或集合。
- 格式处理层:使用专门的库或类,将数据转换为目标格式(CSV, Excel, PDF, HTML等)。
- 输出层:设置正确的HTTP Header,将文件流输出给用户下载,或保存到服务器。
轻量级 & 高可控(纯PHP + 库)
适合对性能、依赖有要求,或需要高度定制化的项目。
CSV 导出(原生PHP,零依赖)
适用于大数据量,通用性强。
<?php
function exportCsv(array $data, string $filename, array $headers = [])
{
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="' . $filename . '.csv"');
// 解决BOM问题(Excel打开中文不乱码)
echo "\xEF\xBB\xBF";
$output = fopen('php://output', 'w');
// 写入表头
if (!empty($headers)) {
fputcsv($output, $headers);
}
// 写入数据
foreach ($data as $row) {
fputcsv($output, $row);
}
fclose($output);
exit;
}
// 使用示例
$data = [
['id' => 1, 'name' => '张三', 'email' => 'a@b.com'],
['id' => 2, 'name' => '李四', 'email' => 'c@d.com'],
];
exportCsv($data, '用户列表', ['ID', '姓名', '邮箱']);
Excel 导出(推荐 PhpSpreadsheet)
相比 PHPExcel, PhpSpreadsheet 是官方维护、性能更好的现代库。
安装:composer require phpoffice/phpspreadsheet
<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
function exportExcelXlsx(array $data, string $filename, array $headers = [])
{
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
// 填充表头
if (!empty($headers)) {
foreach ($headers as $colIndex => $header) {
$sheet->setCellValueByColumnAndRow($colIndex + 1, 1, $header);
}
}
// 填充数据 (从第二行开始)
$rowIndex = 2;
foreach ($data as $row) {
$colIndex = 1;
foreach ($row as $value) {
$sheet->setCellValueByColumnAndRow($colIndex, $rowIndex, $value);
$colIndex++;
}
$rowIndex++;
}
// 输出到浏览器
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="' . $filename . '.xlsx"');
header('Cache-Control: max-age=0');
$writer = new Xlsx($spreadsheet);
$writer->save('php://output');
exit;
}
// 使用示例同上
PDF 导出(推荐 Dompdf 或 TCPDF)
- Dompdf:支持HTML转PDF,适合将视图模板导出为PDF。
- TCPDF:功能更底层、强大,适合精确控制页面布局。
安装:composer require dompdf/dompdf
<?php
use Dompdf\Dompdf;
function exportPdfFromHtml(string $htmlContent, string $filename)
{
$dompdf = new Dompdf();
$dompdf->loadHtml($htmlContent);
$dompdf->setPaper('A4', 'portrait');
$dompdf->render();
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="' . $filename . '.pdf"');
echo $dompdf->output();
exit;
}
// 使用:将视图渲染为HTML字符串
$html = view('exports.user_report', ['users' => $data])->render();
exportPdfFromHtml($html, '用户报告');
企业级 & 低代码(推荐 Laravel Excel + 自定义导出类)
如果你使用 Laravel 框架,这是最推荐的方案,它将导出逻辑完全解耦,大大降低了复杂度。
安装:composer require maatwebsite/laravel-excel
创建导出类
php artisan make:export UsersExport --model=User
定义导出逻辑(编辑 app/Exports/UsersExport.php)
<?php
namespace App\Exports;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
class UsersExport implements FromCollection, WithHeadings, WithMapping
{
public function collection()
{
return \App\Models\User::all(); // 也可以是任意自定义集合
}
public function headings(): array
{
return ['ID', '姓名', '邮箱', '注册时间'];
}
// 数据映射(格式化字段)
public function map($user): array
{
return [
$user->id,
$user->name,
$user->email,
$user->created_at->format('Y-m-d H:i:s'),
];
}
}
在控制器中实现多格式导出
<?php
use App\Exports\UsersExport;
use Maatwebsite\Excel\Facades\Excel;
class ExportController extends Controller
{
public function export(string $format = 'xlsx')
{
$export = new UsersExport();
switch ($format) {
case 'csv':
return Excel::download($export, 'users.csv', \Maatwebsite\Excel\Excel::CSV);
case 'pdf':
return Excel::download($export, 'users.pdf', \Maatwebsite\Excel\Excel::DOMPDF);
case 'html':
return Excel::download($export, 'users.html', \Maatwebsite\Excel\Excel::HTML);
default: // xlsx
return Excel::download($export, 'users.xlsx');
}
}
}
优势:一行代码切换格式,同时支持 xlsx, csv, pdf, html, tsv, ods 等。
关键注意事项
-
内存管理:大数据导出时(如10万行),避免用
model->all()一次性加载,应使用游标或分块查询。- Laravel:
User::cursor()或User::chunk(1000, function($users) { ... }) - 原生PHP:
PDO::query()+ 逐行fetch
- Laravel:
-
文件名处理:避免中文乱码。
rawurlencode($filename)(RFC 5987) 或对HTTP Header进行编码。
-
格式差异:
- CSV/Excel:注意日期、数字格式(不要默认变成科学计数法,需加前导引号或设置列格式)。
- PDF:中文需要加载中文字体(Dompdf默认不支持,需下载中文字体文件并注册)。
-
响应时机:在
header()和echo输出前,确保没有任何其他输出(如空格、BOM头、echo调试)。
- 简单/一次性任务:直接用原生PHP + PhpSpreadsheet + Dompdf,库管理用Composer。
- Laravel框架:直接上 Laravel Excel,开发效率最高。
- 高并发/大文件:考虑异步任务(如 Laravel Queue)处理导出,生成文件后通过通知下载。
需要我针对具体哪种格式或场景(比如超大Excel优化、PDF中文乱码)展开讲解吗?