应改用phpspreadsheet,因phpexcel已停止维护,不兼容php 7.2+及8.x,存在安全漏洞与内存泄漏,且构造函数写法在新版php中废弃;phpspreadsheet为官方继任者,持续维护,支持php 7.4–8.3。

PHPExcel 已停止维护,不建议新项目学习或使用。2026 年还在学它,相当于用 IE6 写前端——能跑,但踩坑多、无更新、不兼容 PHP 8.2+、安全补丁缺失。
真正该学的是它的官方继任者:PhpSpreadsheet。下面直奔实操重点。
为什么不能直接 require 'PHPExcel/Classes/PHPExcel.php'?
常见错误现象:Fatal error: Uncaught Error: Class 'PHPExcel' not found 或 Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP。
根本原因:PHPExcel 基于 PHP 5.2–7.1 设计,其构造函数写法(如 function PHPExcel())在 PHP 7.2+ 中被废弃,且类自动加载逻辑与 Composer 标准不兼容。
解决方案只能是:
- 彻底弃用 PHPExcel
- 改用 PhpSpreadsheet,通过 Composer 安装
- 若必须兼容旧代码,需加 PHP 版本锁(如 .htaccess 或 php.ini 强制 7.1),但生产环境极不推荐
PhpSpreadsheet 加载 Excel 文件时类型识别失败怎么办?
常见错误现象:Could not auto-detect file type,尤其出现在上传文件或文件扩展名被改写(如 data.xls 实际是 CSV)时。
原因:IOFactory::load() 依赖文件头和扩展名双重判断,二者不一致就报错。
解决方法:
- 手动指定读取器类型:$reader = IOFactory::createReader('Xlsx') 或 'Xls' 或 'Csv'
- 对 CSV,额外设置分隔符和编码:$reader->setDelimiter(',')->setEnclosure('"')->setInputEncoding('UTF-8')
- 避免用 createReaderForFile(),它已标记为 deprecated
导出 Excel 时中文乱码或文件打不开?
核心问题不在库本身,而在 HTTP 头和写入时机:
- 必须在 $writer->save('php://output') **之前**输出所有 header,且不能有任何 echo/print 输出(包括 BOM、空格、调试语句)
- 正确的 Content-Type:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet(xlsx)或 application/vnd.ms-excel(xls)
- 文件名含中文时,需 URL 编码:filename="export_'.rawurlencode(date('Ymd').'.xlsx').'
- 如果用 Nginx,确认未启用 fastcgi_buffering off; 类配置,否则可能截断二进制流
大数据量读取内存溢出怎么破?
默认全量加载会把整个 Excel 解析进内存,10 万行 xlsx 很容易吃光 512MB 内存。
两个有效策略:
- 启用只读 + 单元格缓存:$reader->setReadDataOnly(true); $reader->setLoadAllSheets(false);
- 改用流式读取(需配合 Spout 库):spout 不解析样式/公式,纯数据流,内存恒定在几 MB,但仅支持 xlsx 和 csv,不支持 xls
- PhpSpreadsheet 自身不提供流式 API,所谓“分块读取”本质仍是按行迭代,只是避免一次性 fromArray,仍需注意 getCellIterator() 的 setIterateOnlyExistingCells(false) 会强制遍历空列,加剧内存压力
实际项目里最常被忽略的点:没有验证上传文件 MIME 类型就直接丢给 PhpSpreadsheet 处理。攻击者上传伪造的 .xlsx(实为 ZIP/XML/PHP 文件)可能触发反序列化或路径遍历。务必先用 finfo_file() 检查真实类型,再决定是否交给库解析。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











