php读excel必须用phpspreadsheet,phpexcel已停止维护;读.xlsx和.xls需分别用xlsx/xls类,需先判断扩展名;大文件要setreaddataonly或chunkreadfilter防oom;中文乱码需显式设置中文字体。

PHP读Excel必须装phpspreadsheet,不是PHPExcel
旧项目里常看到PHPExcel,但它2015年就停止维护了,PHP 7.2+ 直接报Fatal error: Uncaught Error: Call to undefined method PHPExcel_Worksheet::getCellIterator()这类错误。现在唯一靠谱的选择是phpspreadsheet,Composer安装即可:composer require phpoffice/phpspreadsheet。注意它不依赖ext-xls或ext-excel——PHP本身没有原生Excel扩展,那些名字都是假的。
读.xlsx和.xls文件用的类不一样
phpspreadsheet内部靠不同Reader类解析格式:Xlsx读.xlsx,Xls读.xls(即Excel 97–2003格式)。如果硬用Xlsx去读.xls,会抛出PhpOffice\PhpSpreadsheet\Reader\Exception: Invalid file format。实际写法得先判断后加载:
$extension = pathinfo($file, PATHINFO_EXTENSION);
$reader = match ($extension) {
'xlsx' => new \PhpOffice\PhpSpreadsheet\Reader\Xlsx(),
'xls' => new \PhpOffice\PhpSpreadsheet\Reader\Xls(),
default => throw new InvalidArgumentException('Unsupported extension: ' . $extension)
};
$spreadsheet = $reader->load($file);
内存爆掉?别直接getWorksheetIterator()
大Excel(比如5万行)用$worksheet->toArray()或$worksheet->getHighestRow()前没做限制,PHP进程很容易OOM。根本原因是phpspreadsheet默认把整张表加载进内存。解决方法只有两个:
- 用
setReadDataOnly(true)跳过样式、公式等无用数据 - 对超大文件改用
ChunkReadFilter分块读,比如每次只读1000行 - 确认服务器
memory_limit至少设为256M,512M更稳妥
顺带一提:getHighestRow()在未开启setReadDataOnly时可能返回错误值——空行被算进去了,结果比实际多几百行。
立即学习“PHP免费学习笔记(深入)”;
中文乱码不是编码问题,是字体缺失
导出的Excel里中文显示成方块或问号,不是mb_convert_encoding能解决的。根本原因是phpspreadsheet默认用Calibri字体,而系统没这个字体时,Linux下会fallback到无中文支持的字体。解决方式只有显式设置中文字体:
$styleArray = [
'font' => ['name' => 'SimSun', 'size' => 12],
];
$worksheet->getStyle('A1:Z1000')->applyFromArray($styleArray);
注意:SimSun(宋体)在大多数Linux服务器上也不存在,得提前装fonts-wqy-zenhei或把字体文件放本地路径再用addFont注册。这点容易被忽略,调半天UTF-8反而跑偏。











