4

大数据量导出excel是很常见的一个问题

这里给出一个方案,用到的技术为yii2、phpspreadsheet、zip

任务拆分

首先第一步需要做的就是任务拆分,将一个导出任务拆分为n个来处理   
最终导出n个excel文件。 

数据批获取

这一步要重点说一下,即使做了任务拆分在从数据库批获取拆分后的  
数据时数据量也是很多的,这将导致php进程的内存暴增  

这时就需要使用构造器、迭代器的方式来获取数据  

yii2这边可以直接使用Query查询生成器的each方法来处理就行了  
each就是基于迭代器的一种实现  

each的思路是将查询得到的数据先临时放在数据库服务器中  
在遍历迭代器的时候再分批拉取数据库服务器中的结果数据
这样就可以避免进程内存的暴增问题了
// 拆分任务
foreach($tasks as $task){
    $query = Query::find();
    // 遍历迭代器
    foreach($query->each() as $value){
        //            .
        // 这里拼装数据用于创建$spreadsheet
        //            .
    }
    unset($query);
    //            .
    // 这里导出excel文件
    //            .
}
//            .
// 这里打包所有excel文件
//            .

excel导出资源释放

创建的表格记得及时释放,表格会占用较多内存。  
$spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
//            .
// 这里拼装$spreadsheet
//            .
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
$writer->setPreCalculateFormulas(false);
$writer->save("**********.xlsx");
// 释放表格
$spreadsheet->disconnectWorksheets();
unset($spreadsheet);
unset($writer);

最后压缩打包导出的所有excel

$zip = new ZipArchive();
if ($zip->open('excel.zip', ZipArchive::OVERWRITE) == true) {
    //调用方法,对要打包的根目录进行操作
    addFileToZip('excel/', $zip); 
    $zip->close();
}
unset($zip)

吃饭饭睡觉觉
62 声望4 粉丝