使用 Laravel 导出 1000 万行以上的 XLSX 文件而不会出现内存问题
关于 FastExcel
发电机
使用 FastExcel 和生成器导出大型数据集
由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!
TL;DR:本文介绍了 Laravel 的 FastExcel,快速概述了 PHP 生成器,并最终展示了如何将两者结合使用,在节省内存的同时从集合生成 Excel 文件。
关于 FastExcel
Laravel FastExcel旨在成为 Laravel 风格的Spout,目标是简化导入和导出操作。它可以被视为Laravel Excel的一个更快(且更节省内存)的替代方案,但采用了不同的方法,功能也更少。只需两步即可上手。
使用 Composer 安装:
composer require rap2hpoutre/fast-excel
然后将模型或集合导出到XLSX,CSV或者ODS:
fastexcel($collection)->export('file.xlsx');
发电机
生成器是在 PHP 5 中引入的,距今已有多年。生成器函数看起来和普通函数没什么区别,不同之处在于它不返回值,而是生成值。然后你可以遍历生成器函数。
此类函数的目标之一是无需构建数组即可对数据进行惰性迭代。因此,在处理大型数据集时,它可以节省内存。引用PHP 文档:
生成器允许你编写使用 foreach 循环遍历一组数据的代码,而无需在内存中构建数组,这可能会导致超出内存限制,或者需要大量的处理时间来生成。
假设你的User数据库中有一个包含 1000 万条以上记录的模型,并且你想在代码中遍历它,那么除了直接调用 `get()` 方法之外User::all(),你还可以使用生成器:
function usersGenerator() {
foreach (User::cursor() as $user) {
yield $user;
}
}
$users = usersGenerator();
foreach($users as $user) {
// Do something with each user without hitting memory limit
}
上述示例运行查询时,每次只获取一个用户。它仅使用加载一个用户所需的内存N。
使用 FastExcel 和生成器导出大型数据集
自 v1.3.0 版本起,FastExcel接受生成器函数作为参数。以前面的示例为例,您可以直接将生成器传递给fastexcel函数:
function usersGenerator() {
foreach (User::cursor() as $user) {
yield $user;
}
}
// Export consumes only a few MB, even with 10M+ rows.
$users = usersGenerator();
fastexcel($users)->export('test.xlsx');
FastExcel在使用生成器时会逐行创建数据,因此不会占用额外内存。但这个过程会比较耗时,所以请确保它不会造成服务器宕机max_execution_time(您可以使用队列、任何异步技术、增加最大执行时间,甚至可以从命令行运行)。不过,服务器仍然会感谢它不会因为一次导出就占用所有内存。
因此,借助生成器,现在只需在 Laravel 项目中编写几行代码,即可将数千个模型导出到XLSX.jsCSV和 .xml文件。ODS
您可以在代码仓库中了解更多关于该库的信息:https://github.com/rap2hpoutre/fast-excel
文章来源:https://dev.to/rap2hpoutre/export-10m-rows-in-xlsx-with-laravel-without-memory-issues-6bk