目录一、前言二、解决方案三、示例一、前言之前做数据批量导出一直都是用的PHPExcel插件一个是由于现在PHPExcel已经不再维护了一个是如果导出大批量数据导出的表格就会提示数据损坏、文件不完整之类的提示就是打不开文件其核心原因就是由于PHPExcel的工作原理是先把所有的数据行都查出来加载放到内存中再进行写入如果数据量小还可以如果数据量大内存占用急剧增加就会导致内存不足或者请求超时导致生成的文件不完整。二、解决方案有两种解决方案一种是直接导出CSV格式的文件代码比较简单一种是使用PhpSpreadsheet插件这里只介绍CSV格式因为对于几十万行的数据已经够用了。原理CSV是纯文本格式逐行写入几乎不消耗额外内存支持几十万行数据无压力。优势① 内存占用~10M② 5000条执行时间~1秒③ 支持最大行数100万④ 兼容excel打开文件⑤ 代码复杂度低。三、示例public function downai(){ // 设置脚本不超时 set_time_limit(0); // 设置下载头 $filename export_ . date(YmdHis) . .csv; header(Content-Type: text/csv; charsetutf-8); header(Content-Disposition: attachment; filename . $filename . ); // 清空缓冲区 ob_end_clean(); // 打开输出流 $fp fopen(php://output, w); // 写入BOM头解决中文乱码 fwrite($fp, \xEF\xBB\xBF); // 表头 $headers [ 文章ID, 批次, 文章标题, 信息平台, 发布者 ]; // 写入表头 fputcsv($fp, $headers); // 使用 chunk 分批处理每批500条 Db::table(article_artificial) -alias(a) -join(article_base b, a.article_id b.id) -field(a.*, b.title, b.fabu_time, b.pingtai, b.faburen, b.kind) -where(b.pici_id, $pici_id) -chunk(500, function($items) use ($fp, $pici) { // 写入内容 foreach ($items as $v) { // 要写入的字段 $row [ $v[article_id], // 文章ID $pici, // 批次 $v[title], // 文章标题 $v[pingtai], // 信息平台 $v[faburen] // 发布者 ]; // 写入 fputcsv($fp, $row); } // 刷新缓存区 if (ob_get_level() 0) { ob_flush(); } flush(); },a.id,asc); // 关闭 fclose($fp); exit; }使用chunk对大批量数据进行分批处理每次处理500条减少内存压力chunk用法chunk($size, $callback, $column null, $order asc)参数说明$sizeint每批处理多少条数据举例500$callbackcallable处理每一批数据的回调函数举例function($items) { ... }$columnstring用于分页排序的字段名必须是主键或唯一索引的数值字段举例id$orderstring排序方式举例asc或desc核心限制$column和$order是chunk内部实现分批查询的依据因此不能在调用chunk()之前再用链式操作否则就会产生冲突。