做后臺(tái)系統(tǒng)的開發(fā)者幾乎都遇到過這個(gè)場景:運(yùn)營同事要一份"用戶+訂單"的匯總報(bào)表,數(shù)據(jù)量不大,但分屬兩張表。最直覺的做法是寫兩個(gè)導(dǎo)出按鈕,或者把數(shù)據(jù)合并到一張表。前者體驗(yàn)差,后者結(jié)構(gòu)亂。其實(shí)Laravel生態(tài)里有個(gè)更干凈的解法——多Sheet單文件導(dǎo)出。
這篇技術(shù)筆記來自一位印尼開發(fā)者的實(shí)踐,核心依賴是maatwebsite/excel 3.1版本。整個(gè)方案五步走完,但第四步的設(shè)計(jì)值得細(xì)品。
![]()
先看前端。兩個(gè)日期選擇框加一個(gè)導(dǎo)出按鈕,點(diǎn)擊后把起止時(shí)間拼進(jìn)URL參數(shù),走GET請求到后端。沒有用什么花哨的異步交互,就是最簡單的window.location.href跳轉(zhuǎn)。這種"樸素"反而減少了出錯(cuò)面——導(dǎo)出本來就是耗時(shí)操作,讓用戶等個(gè)頁面加載,比假裝即時(shí)響應(yīng)更誠實(shí)。
控制器里的邏輯分層很清楚。從request里取日期范圍,分別查users表和orders表,各取兩列,最后map成二維數(shù)組。這里有個(gè)注釋值得注意:如果查詢變慢,建議拆Sheet并配合FromQuery和WithChunkReading。這不是廢話——當(dāng)單表數(shù)據(jù)過百萬行時(shí),一次性get()會(huì)直接把內(nèi)存撐爆。但示例代碼為了可讀性,用了最簡單的get()->map(),把優(yōu)化空間留給了注釋。
真正的設(shè)計(jì)在Export類和Sheet類。MyExport實(shí)現(xiàn)WithMultipleSheets接口,構(gòu)造函數(shù)收兩個(gè)數(shù)據(jù)集,sheets()方法返回兩個(gè)MySheet實(shí)例,分別命名'Users'和'Orders'。這種"一個(gè)類管文件,一個(gè)類管Sheet"的分層,讓代碼有了復(fù)用性——下次要導(dǎo)"用戶+商品+庫存"三張表,改一下sheets()方法的返回?cái)?shù)組就行。
MySheet類更細(xì)。它同時(shí)實(shí)現(xiàn)FromArray和WithTitle,array()方法里根據(jù)title判斷表頭:Users表輸出NAME/EMAIL,Orders表輸出INVOICE/TOTAL。這里用了if分支而不是傳參配置,看起來不夠"優(yōu)雅",但勝在直觀。畢竟報(bào)表的表頭很少變動(dòng),硬編碼比抽象層更不容易出錯(cuò)。
整個(gè)方案沒有涉及隊(duì)列、沒有分片下載、沒有前端進(jìn)度條。它解決的是一個(gè)特定規(guī)模的問題:數(shù)據(jù)量中等、實(shí)時(shí)性要求不高、需要多表關(guān)聯(lián)呈現(xiàn)的場景。如果你的導(dǎo)出任務(wù)超過這個(gè)邊界,注釋里提到的FromQuery和WithChunkReading就是下一步。
最后提一下作者留下的聯(lián)系方式。raflizocky.netlify.app,PayPal和Saweria的打賞鏈接——典型的獨(dú)立開發(fā)者做內(nèi)容變現(xiàn)的路子。技術(shù)文檔本身免費(fèi),信任建立后轉(zhuǎn)化外包需求。這種模式在東南亞開發(fā)者社區(qū)很常見,比國內(nèi)"引流私域再賣課"的路徑更直接。
特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺(tái)“網(wǎng)易號”用戶上傳并發(fā)布,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.