iT邦幫忙

2026 iThome 鐵人賽

DAY 20
0
Modern Web

Laravel Filament 從入門到實戰系列 第 20 篇

Day 19:第一個 Widget,把訂單數字擺上首頁

  • 分享至 

  • xImage
  •  

Day 18:權限與租戶疊加時,驗證兩者不互相打架 結尾留下一句話,這套後台的身分跟邊界已經穩固,但管理者如果想知道現在有多少筆待處理的訂單、庫存還剩多少,仍然得逐一點開商品、訂單這幾個 Resource,才能一點一點拼湊出目前的現況,後台目前沒有一個地方,能讓人一打開就看懂整體現況。今天要處理的正是這句話,也是第六階段「Widget 與客製化儀表板」的第一天。

資料都在,首頁卻什麼都看不到

打開目前這套後台的首頁,畫面跟 Day 02:安裝與第一個 Panel,認識這個後台入口容器 剛裝好時相去不遠,一片空白,或者頂多是 Panel 預設的極簡歡迎畫面。

這件事本身相當弔詭,因為經過前面十八天,這套系統裡其實已經累積了不少貨真價實的資料,商品、訂單、客戶、訂單明細,每一個模組都撐起了自己的列表頁與表單,甚至連角色權限跟多租戶隔離都上線驗證過了。資料齊全,機制也齊全,唯獨首頁這個入口進來第一眼看到的地方,什麼都沒有。

具體想像管理者每天上班的第一件事。他想知道今天有沒有新訂單需要處理,得先點開訂單列表,掃過一遍狀態欄位;想知道庫存夠不夠,又得切到商品列表,一筆一筆核對數量。這幾個列表頁各自都做得完整、可操作、可分頁,沒有任何一個環節是壞的,問題出在沒有一個地方能把這些分散的資訊濃縮成幾個關鍵數字,讓人一進後台就掌握現況。管理者手上握著的是一套功能齊全的系統,卻得靠自己每天重複點開好幾個頁面,才能拼湊出「現在情況如何」這個最基本的問題的答案。

今天的任務,是正式定案 Filament 裡負責填補這個落差的機制,讓後台首頁第一次顯示出有意義的統計數字。這個機制能呈現的內容其實不只統計數字一種,今天先聚焦在最基礎、也最常見的這一種類型,其餘的留到接下來兩天處理。

定案 Widget,首頁上的資訊區塊

先把這個機制的定義講清楚:Widget,顯示在 Panel 首頁或個別頁面上的資訊區塊,可為統計數字、圖表或自訂內容。這是全系列第一次正式使用這個詞,接下來只要提到後台首頁上這類濃縮呈現的資訊區塊,指的都是 Widget。

這個定義裡藏著三種內容類型,值得逐一拆開來看。

統計數字類型:呈現的是單一個濃縮過的數值,例如本月訂單數,把一整個資料表的查詢結果壓縮成一個數字,管理者掃一眼就懂,不需要理解背後的查詢邏輯。

圖表類型:把一段時間內的資料變化畫成視覺化的曲線或長條,服務的是「這個數字是在往上走還是往下走」這種需要看趨勢的情境。

自訂內容類型:則完全不受限於數字或圖表的形式,可以是任何形式的畫面區塊,彈性最大,也最考驗設計者對這個位置該放什麼內容的判斷。今天的示範只會碰到第一種,圖表類型放到明天再展開。

這裡也適合把 Widget 跟前面十八天一直在打磨的 Resource 列表頁放在一起比較,兩者乍看都是在呈現資料,性質卻完全不同。

Resource 列表頁服務的是需要逐筆檢視或編輯資料的情境,一張完整、可操作、可分頁的清單,管理者要改一筆訂單狀態,得靠這個介面。

Widget 服務的是完全相反的情境,管理者不想進入任何一筆資料細節,只想在最短時間內知道現在的整體現況,一個數字、一張圖表就足夠。

兩者不是誰取代誰的關係,而是互補,列表頁負責深入,Widget 負責一眼看懂。用儀表板上的時速表來類比會更直觀,開車時不需要自己拿里程數除以行駛時間去算出目前的速度,時速表已經把這個計算結果直接攤在眼前,Widget 在後台首頁扮演的正是這個角色。

動手做統計數字,本月訂單數與待處理訂單數

定義釐清之後,回到示範專案,實際做出第一個統計數字類型的 Widget。Filament 提供了一個現成的基底類別,專門處理這種「一排統計數字」的呈現需求,透過指令產生骨架:

php artisan make:filament-widget OrderStatsOverview --stats-overview

指令跑完,app/Filament/Widgets 資料夾裡會多出 OrderStatsOverview.php,內容大致如下:

<?php

namespace App\Filament\Widgets;

use App\Models\Order;
use Filament\Widgets\StatsOverviewWidget as BaseWidget;
use Filament\Widgets\StatsOverviewWidget\Stat;

class OrderStatsOverview extends BaseWidget
{
    protected function getStats(): array
    {
        $monthlyOrderCount = Order::query()
            ->whereBetween('created_at', [now()->startOfMonth(), now()->endOfMonth()])
            ->count();

        $pendingOrderCount = Order::query()
            ->where('status', 'pending')
            ->count();

        return [
            Stat::make('本月訂單數', $monthlyOrderCount)
                ->description('統計本月建立的訂單筆數'),

            Stat::make('待處理訂單數', $pendingOrderCount)
                ->description('尚未確認或出貨的訂單')
                ->descriptionIcon('heroicon-m-clock')
                ->color($pendingOrderCount > 0 ? 'warning' : 'success'),
        ];
    }
}

第一個統計數字,取用訂單資料表,計算本月建立的訂單筆數,查詢條件用的是 created_at 落在本月區間這個既有欄位,沒有引入任何新的資料結構。第二個統計數字,呼應 Day 09:表單裡選關聯資料,下拉選單背後在做什麼 定案的訂單狀態欄位,計算目前處於待處理狀態的訂單筆數,讓管理者一眼看到有多少筆訂單卡在需要盡快處理的階段。description 補上一句簡短的說明文字,color 依待處理筆數是否大於零切換顏色,這類小裝飾能替統計數字加一點層次,但重點還是這個數字本身,不需要為了美觀延伸出額外的圖表或曲線,那會模糊掉統計數字類型該有的簡潔性質。

寫好類別之後,還差一步,把它掛到 Panel 首頁上。回到 Day 2 建立的 AdminPanelProvider.php,這個檔案裡原本就有一行 discoverWidgets,指向 app/Filament/Widgets 這個資料夾,剛才建立的 OrderStatsOverview 只要放在這個資料夾底下,Panel 啟動時就會自動掃描到,不需要額外註冊路由或處理版面配置。這正呼應 Day 2 定案的 Panel 定義,Filament 裡一個獨立後台入口的最上層容器,Widget 正是這個容器首頁上其中一種可以自動掛載的內容,跟 Resource 走的是同一套自動掃描機制。

驗證成果,第一次打開後台就看懂現況

程式碼寫完,回到瀏覽器實際操作一次。登入後台,這次首頁不再是空白畫面,最上方出現兩張卡片,一張顯示本月訂單數,一張顯示待處理訂單數,數字直接呈現,不需要點開任何一個 Resource 列表頁,也不需要自己在腦中拼湊查詢邏輯。

Panel 首頁,OrderStatsOverview 掛載後

這一刻值得停下來多看兩秒。這是全系列第一次,登入這套後台看到的不再是一個等待被操作的空殼,而是一個真正能傳遞資訊的畫面。

首頁從一張白紙,變成貼了幾張便利貼,管理者不需要知道背後那段查詢語法怎麼寫,也不需要理解 whereBetween 或 where('status', 'pending') 這些條件是怎麼組出來的,卡片上的數字已經把答案準備好了。這正是第六階段一開始設定的目標,把系列前面累積的資料,第一次轉化成管理者一眼就能看懂的畫面。

數字看到了,但看不出來走勢

今天做的事情可以濃縮成一句話,正式定案了 Widget 這個資訊區塊,顯示在 Panel 首頁或個別頁面上,可以是統計數字、圖表或自訂內容,並且在後台首頁示範了本月訂單數與待處理訂單數這兩個統計數字類型的 Widget,把原本得逐一點開列表頁才拼湊得出來的現況,變成打開後台就能立刻看到的資訊。

但這裡也得誠實面對統計數字類型的侷限。今天卡片上看到的每一個數字,都只是當下這個時間點的切片。本月訂單數如果是二十五筆,這二十五筆究竟是比上個月成長還是萎縮,光看這一個數字完全感受不到,庫存或訂單量的變化過程也是同樣的道理,數字本身不會告訴你方向。要看出趨勢往哪裡走,得靠另一種呈現方式才行。

圖表 Widget,讓庫存與訂單趨勢一眼看懂,是接下來要處理的內容。


上一篇
Day 18:權限與租戶疊加時,驗證兩者不互相打架
系列文
Laravel Filament 從入門到實戰 共 20 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言