PHP项目如何实现多格式导出?

wen PHP项目 3

本文目录导读:

PHP项目如何实现多格式导出?

  1. 核心架构设计
  2. 方案一:轻量级 & 高可控(纯PHP + 库)
  3. 方案二:企业级 & 低代码(推荐 Laravel Excel + 自定义导出类)
  4. 关键注意事项

这是一个很实用的需求,在PHP项目中实现多格式导出,核心思路通常是数据统一抽离 + 格式差异化处理

我会为你梳理一个完整、可扩展的架构方案,并提供核心代码示例。

核心架构设计

  1. 数据层:从数据库或API查询原始数据,统一处理成数组或集合。
  2. 格式处理层:使用专门的库或类,将数据转换为目标格式(CSV, Excel, PDF, HTML等)。
  3. 输出层:设置正确的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)

相比 PHPExcelPhpSpreadsheet 是官方维护、性能更好的现代库。

安装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 等。


关键注意事项

  1. 内存管理:大数据导出时(如10万行),避免用 model->all() 一次性加载,应使用游标分块查询

    • Laravel: User::cursor()User::chunk(1000, function($users) { ... })
    • 原生PHP: PDO::query() + 逐行fetch
  2. 文件名处理:避免中文乱码。

    • rawurlencode($filename) (RFC 5987) 或对HTTP Header进行编码。
  3. 格式差异

    • CSV/Excel:注意日期、数字格式(不要默认变成科学计数法,需加前导引号或设置列格式)。
    • PDF:中文需要加载中文字体(Dompdf默认不支持,需下载中文字体文件并注册)。
  4. 响应时机:在 header()echo 输出前,确保没有任何其他输出(如空格、BOM头、echo调试)。

  • 简单/一次性任务:直接用原生PHP + PhpSpreadsheet + Dompdf,库管理用Composer。
  • Laravel框架:直接上 Laravel Excel,开发效率最高。
  • 高并发/大文件:考虑异步任务(如 Laravel Queue)处理导出,生成文件后通过通知下载。

需要我针对具体哪种格式或场景(比如超大Excel优化、PDF中文乱码)展开讲解吗?

抱歉,评论功能暂时关闭!