iT邦幫忙

2026 iThome 鐵人賽

DAY 29
0
Software Development

一套真實運作中的 Laravel 系統,拆解它的原生機制系列 第 29 篇

Day 29:全站審計——一個套件的能力邊界,跟怎麼延伸它涵蓋原生不支援的事件

  • 分享至 

  • xImage
  •  

前言:「誰改的?什麼時候改的?改之前是什麼樣子?」

「這筆資料現在的內容不對,但沒人知道是誰、什麼時候改的。」

這句話是很多系統維運過程裡,遲早會聽到的抱怨。異動稽核(audit trail)要解決的正是這個問題:記錄下「誰、什麼時候、把什麼欄位、從什麼值改成什麼值」。今天要看的是這個系列素材專案怎麼導入稽核套件,以及一個更值得記住的延伸案例——當套件原生只涵蓋一部分情境,怎麼把它擴展到套件本身沒有考慮到的事件。

今日目標

  • 理解異動稽核(audit trail)在解決什麼問題,為什麼值得在專案早期就導入
  • 看一個真實案例:全站所有 Model 加上稽核功能是怎麼做到的
  • 認識套件的能力邊界:稽核套件原生只涵蓋 Model 的 CRUD 事件
  • 看這個邊界怎麼被延伸,讓「登入」這種非 CRUD 事件也被納入同一套稽核記錄

本文主體

第一步:全站所有 Model 加上稽核功能

這個系列的素材專案用了 laravel-auditing 這個套件來處理異動稽核。這類套件的核心運作方式是:Model 實作套件要求的介面、使用套件提供的 trait,套件會在 Model 儲存、更新、刪除的時候自動攔截這些事件,把異動內容(改動前的值、改動後的值、操作者是誰)寫進一張獨立的稽核紀錄表。

在某次 commit 紀錄裡,可以看到「為所有 Model 加入 laravel-auditing 審計功能」這樣的描述——這是一次系統性的改動,把套件要求的介面跟 trait,套用到專案裡幾乎每一個 Model 上。這代表從那次改動之後,任何一筆 News、Page、Banner 之類的資料被新增、修改、刪除,都會自動留下一筆可追溯的紀錄,不需要每個 Model 各自手動實作記錄邏輯。

套件的能力邊界:只涵蓋 Model 的 CRUD 事件

套件把「Model 異動」這類事件處理得很完整,但這裡有一個容易被忽略的邊界:laravel-auditing 原生設計的稽核對象,是 Model 的新增/修改/刪除這幾種 Eloquent 事件。它天生不會知道「使用者登入了」這種完全不牽涉 Model 資料異動的事件,因為登入本身不是在改動某一筆 Model 的欄位。

如果系統的稽核需求只到「資料被誰改了」,套件的原生能力就已經夠用。但如果需求擴大到「誰在什麼時候登入過系統」這種安全稽核情境,套件原生就沒有現成的機制可以直接套用。

延伸案例:把登入事件也塞進同一套稽核記錄

這個系列的素材專案有另一次 commit,描述是「登入事件寫入 laravel-auditing 審計記錄」。這次改動做的事情是:監聽 Laravel 內建的登入事件,在事件觸發時,手動組出一筆符合套件稽核紀錄格式的資料,寫進跟 Model 異動共用的那張稽核紀錄表。

這個做法的巧妙之處在於:它沒有為登入事件另外開一張獨立的資料表、另外做一套查詢介面,而是讓登入事件「假裝」自己也是一筆套件認得的稽核紀錄,寫進同一張表。這樣後台如果已經有一個查看稽核紀錄的介面,不需要額外開發,登入紀錄自然而然也會出現在同一個地方,跟 Model 異動紀錄混在一起依時間排序查看。

用一組對照來看這個設計決策:

❌ 為登入事件另外開一套稽核機制
→ 需要新的資料表、新的查詢介面、新的權限控管,
  維運時要分別去兩個地方查「這個人做過什麼」

✅ 監聽登入事件,手動組出套件認得的稽核紀錄格式,
   寫進同一張稽核表
→ 沿用既有的稽核紀錄查詢介面跟權限控管,
  登入紀錄跟資料異動紀錄可以放在同一個時間軸上查看,
  不需要重新造一套機制

這個模式背後的通用啟示:先問「套件的資料格式能不能被手動組出來」

這個案例值得抽象成一個更通用的判斷方式:當你需要稽核/記錄某個套件原生不支援的事件類型時,先別急著自己另開一套獨立機制。先看套件本身儲存資料的格式是不是清楚、穩定,能不能透過套件提供的方法(或是直接組出符合格式的資料)手動寫入一筆——如果可以,用這個方式沿用套件既有的查詢介面跟基礎設施,通常比另起爐灶更划算,日後維護的地方也更少一處。

這裡也剛好呼應這個系列前幾天提過的 Listener 機制(監聽登入事件的邏輯,正是用 Laravel 的 Event/Listener 機制實作的)——Listener 負責「監聽到事件之後該做什麼」,這裡的答案就是「組一筆稽核紀錄,寫進既有的稽核表」。

今日思考題

回想你的專案裡,有沒有一個套件的稽核/記錄功能,只涵蓋了部分你關心的事件類型?那些沒被涵蓋到的事件,你會怎麼判斷是該延伸套件既有的資料格式,還是真的需要另開一套獨立機制?

今日重點回顧

  • 異動稽核記錄「誰、什麼時候、改了什麼」,laravel-auditing 這類套件透過 Model trait 自動攔截 CRUD 事件完成這件事
  • 套件的能力邊界:原生只涵蓋 Model 的新增/修改/刪除事件,不會知道登入這種非 Model 異動的事件
  • 真實延伸案例:監聽登入事件,手動組出符合套件格式的稽核紀錄,寫進同一張表,沿用既有查詢介面
  • 通用判斷方式:套件原生不支援的事件類型,先看能不能手動組出符合套件格式的資料寫入,比另開一套機制更划算

明日預告

明天是這個系列的最後一篇,要回頭看這 29 天走過的四大部分,整理出這個系列真正想傳達的一句話——不靠額外框架特性,光是把 Laravel 原生機制用紮實,能撐起什麼樣的真實系統。


上一篇
Day 28:一次資料遷移——dry-run/chunk/三種結果統計,安全搬歷史資料的範本
下一篇
Day 30:總結——不靠額外框架特性,光是把 Laravel 原生機制用紮實,能撐起什麼
系列文
一套真實運作中的 Laravel 系統,拆解它的原生機制 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言