做后台系统的开发者几乎都遇到过这个场景:运营同事要一份"用户+订单"的汇总报表,数据量不大,但分属两张表。最直觉的做法是写两个导出按钮,或者把数据合并到一张表。前者体验差,后者结构乱。其实Laravel生态里有个更干净的解法——多Sheet单文件导出。
这篇技术笔记来自一位印尼开发者的实践,核心依赖是maatwebsite/excel 3.1版本。整个方案五步走完,但第四步的设计值得细品。
先看前端。两个日期选择框加一个导出按钮,点击后把起止时间拼进URL参数,走GET请求到后端。没有用什么花哨的异步交互,就是最简单的window.location.href跳转。这种"朴素"反而减少了出错面——导出本来就是耗时操作,让用户等个页面加载,比假装即时响应更诚实。
控制器里的逻辑分层很清楚。从request里取日期范围,分别查users表和orders表,各取两列,最后map成二维数组。这里有个注释值得注意:如果查询变慢,建议拆Sheet并配合FromQuery和WithChunkReading。这不是废话——当单表数据过百万行时,一次性get()会直接把内存撑爆。但示例代码为了可读性,用了最简单的get()->map(),把优化空间留给了注释。
真正的设计在Export类和Sheet类。MyExport实现WithMultipleSheets接口,构造函数收两个数据集,sheets()方法返回两个MySheet实例,分别命名'Users'和'Orders'。这种"一个类管文件,一个类管Sheet"的分层,让代码有了复用性——下次要导"用户+商品+库存"三张表,改一下sheets()方法的返回数组就行。
MySheet类更细。它同时实现FromArray和WithTitle,array()方法里根据title判断表头:Users表输出NAME/EMAIL,Orders表输出INVOICE/TOTAL。这里用了if分支而不是传参配置,看起来不够"优雅",但胜在直观。毕竟报表的表头很少变动,硬编码比抽象层更不容易出错。
整个方案没有涉及队列、没有分片下载、没有前端进度条。它解决的是一个特定规模的问题:数据量中等、实时性要求不高、需要多表关联呈现的场景。如果你的导出任务超过这个边界,注释里提到的FromQuery和WithChunkReading就是下一步。
最后提一下作者留下的联系方式。raflizocky.netlify.app,PayPal和Saweria的打赏链接——典型的独立开发者做内容变现的路子。技术文档本身免费,信任建立后转化外包需求。这种模式在东南亚开发者社区很常见,比国内"引流私域再卖课"的路径更直接。
热门跟贴