maatwebsite/excel 4.x 必须用 Export 类实现 FromCollection 或 FromQuery 接口,废弃 Excel::create();Facade 需手动注册,推荐依赖注入;FromQuery 更省内存,中文乱码需设中文字体,大文件导出应流式处理并调优服务器配置。

用 maatwebsite/excel 导出 Excel 最快路径
直接装包、注册服务、写控制器方法,三步能跑起来。但别急着复制粘贴,maatwebsite/excel 从 3.x 升到 4.x 后,Excel::create() 和 Excel::export() 完全废弃,现在必须用 Export 类 + FromCollection 或 FromQuery 接口。
常见错误是照着老教程写 Excel::download(new UsersExport, 'users.xlsx') 却报 Class "Excel" not found——那是 Laravel 10+ + maatwebsite/excel 4.x 的典型症状,因为 Facade 默认没注册,得手动加到 config/app.php 的 'aliases' 里:
use Maatwebsite\Excel\Facades\Excel; 'Excel' => Excel::class,
不过更推荐跳过 Facade,直接用依赖注入或门面调用方式,避免配置遗漏。
FromCollection vs FromQuery 怎么选
导出量小(FromCollection;导出量大(>10k 行)、不想把全部数据 load 进内存、数据库字段基本直出,优先用 FromQuery。
容易踩的坑:
-
FromCollection的collection()方法返回的是Collection实例,不是数组——别直接return $users->toArray(),得return new Collection($users) -
FromQuery要求实现query()方法,返回Builder对象,不能提前->get(),否则失去流式导出意义 - 用
FromQuery时,map()回调里不能访问 Eloquent 关系(如$user->profile),因为没 eager load;要关联字段,得在 query 里select()或join()
导出中文表头和单元格乱码怎么办
不是编码问题,是 PHPExcel / PhpSpreadsheet 默认不设 UTF-8 字体,中文会 fallback 到不支持中文的字体(比如 Calibri),显示成方块或空白。
解决方式统一:在 Export 类里加 registerEvents() 方法,强制设字体:
public function registerEvents(): array
{
return [
AfterSheet::class => function(AfterSheet $event) {
$event->sheet->getStyle('A1:Z1000')->getFont()->setName('Microsoft YaHei');
},
];
}
注意点:
- 字体名必须是系统实际存在的,Linux 服务器常缺中文字体,得先装
fonts-wqy-zenhei或上传 ttf 文件并用PhpSpreadsheet\Shared\Font::setCacheStorage()注册 - 别在
map()里动态改样式——性能爆炸,样式应在registerEvents或columnFormats()中批量设 - 如果只导数字和 ASCII,乱码大概率是 BOM 头导致,检查导出响应头是否含
utf8_encode()之类多余转换
大文件导出卡死或超时
Laravel 默认执行时间 30 秒,导出 5w 行 Excel 基本必超时。别急着调 set_time_limit(0),那只是掩盖内存和 IO 问题。
真正有效的做法:
- 用
FromQuery替代FromCollection,配合chunkById()让 PhpSpreadsheet 流式读库,内存占用从几百 MB 降到几 MB - Nginx 需加
fastcgi_read_timeout 600;,否则 60 秒就断连,前端看到空响应 - Apache 下确保
mod_php没开zlib.output_compression,它会干扰 Excel 二进制流,导致文件打不开 - 别在本地开发环境测大数据量——Homestead/Valet 的 PHP 内存限制太低,
php.ini里memory_limit至少设为512M
导出逻辑一旦涉及复杂计算、多次 DB 查询或第三方 API 调用,就得拆成队列任务;Excel 生成本身不适合塞进队列,但数据准备可以——这是最容易被忽略的分层点。











