技術債滾成雪球之前:Laravel 10 潔淨架構重構與維護指南
☰ 目錄 table-of-contents.md
當初讓老闆讚不絕口的「快速功能」,現在自己重讀一次要花多久才看得懂?許多企業級系統為了求穩還停在 Laravel 10,時間一拉長,那些走捷徑的程式碼全滾成了義大利麵與技術債雪球。這篇分享我替舊專案導入潔淨架構的重構與維護心法,趕在雪球壓垮團隊之前把它拆掉。
雖然 Laravel 10 在當年是個長期支援版本(LTS),引入了 PHP 8.1+ 的強型別特性,但工具再好,架構還是得靠人來維護。我看過太多專案,Controller 寫得比聖經還厚,Model 裡面混雜著商業邏輯和視圖邏輯。今天,我們不談那些虛無飄渺的理論,我會以 2026 年的工程標準,回頭檢視「Laravel 10 專案架構最佳實務」,教你如何把手中的技術債,重構成可擴展的資產。
1. 拒絕「肥大 Controller」:擁抱 Action 模式
這是老生常談,但直到 2026 年的今天,我 Review 程式碼時還是會血壓升高。Controller 的職責只有三個:接收請求、呼叫邏輯、回傳回應。它不應該知道你的商業邏輯細節。
在 Laravel 10 時代,雖然 Service Pattern 很流行,但後來我們發現單一職責的 Action Pattern(或稱 Single Action Controller 風格的類別)更容易測試與維護。
糟糕的寫法(The Bad Way):
// StoreController.php
public function store(Request $request)
{
// 驗證邏輯混在 Controller
$request->validate(['email' => 'required|email']);
// 商業邏輯直接寫死
$user = User::create($request->all());
// 發送信件邏輯也塞在這裡
Mail::to($user)->send(new WelcomeEmail($user));
return response()->json($user);
}
2026 年推薦的架構(The Clean Way):
將邏輯抽離到 Action 類別中。這在 Laravel 10 完全適用,且符合未來的升級路徑。
// app/Actions/RegisterUserAction.php
class RegisterUserAction
{
public function execute(UserData $data): User
{
$user = User::create($data->toArray());
// 這裡可以放更多複雜的邏輯,例如觸發事件
UserRegistered::dispatch($user);
return $user;
}
}
// StoreController.php
public function store(RegisterRequest $request, RegisterUserAction $action)
{
// 使用 DTO (Data Transfer Object) 傳遞資料,更加嚴謹
$user = $action->execute(UserData::fromRequest($request));
return UserResource::make($user);
}
這樣做的好處是,這個 RegisterUserAction 可以在 API、CLI 命令列、甚至排程任務中重複使用,而不需要複製貼上程式碼。
2. 強型別與 DTO:別再用陣列傳遞資料
Laravel 10 支援 PHP 8.1/8.2,這意味著我們有很好的型別系統。但在舊專案中,我常看到工程師喜歡把 $request->all() 或是關聯式陣列(Associative Array)到處傳。這在小專案沒問題,但在企業級架構中,這是災難。
如果你在 2026 年還在維護 Laravel 10 專案,請引入 Data Transfer Objects (DTO)。你可以使用 Spatie 的 `laravel-data` 套件,或是 PHP 8.2 的 `readonly` 類別來實作。
為什麼要這麼做? 因為 $data['email'] 沒有 IDE 自動補全,如果你拼錯成 $data['emial'],程式要跑起來才會報錯。但 $data->email 在你寫程式的當下,靜態分析工具就會告訴你錯了。
3. 模型(Model)瘦身計畫:Scope 與 Accessor 的應用
很多工程師會把查詢邏輯直接寫在 Controller 裡,導致重複查詢。請善用 Laravel 的 Local Scopes。
// Bad: 在 Controller 到處寫 where
$activeUsers = User::where('active', 1)->where('last_login', '>', now()->subDays(30))->get();
// Good: 在 Model 定義 Scope
// User.php
public function scopeActive(Builder $query): void
{
$query->where('active', 1);
}
public function scopeRecent(Builder $query): void
{
$query->where('last_login', '>', now()->subDays(30));
}
// Use in Controller
$activeUsers = User::active()->recent()->get();
這不僅讓程式碼具有「語意化」(讀起來像英文句子),如果未來「活躍用戶」的定義改變了(例如從 30 天變成 7 天),你只需要改 Model 一個地方,不用全專案搜尋取代。
4. 依賴注入與介面(Interface)
雖然 Laravel 的 Facade(如 Log::info())很方便,但在大型架構中,過度依賴靜態呼叫會讓測試變得困難。在 Laravel 10 專案重構時,試著使用依賴注入(Dependency Injection)。
定義一個 PaymentGateway 介面,而不是直接在程式碼中 `new StripeService()`。這樣在 2026 年,當業務端突然說要從 Stripe 換成 HitPay 或 ECPay 時,你不需要改動核心商業邏輯,只需要抽換 Service Provider 綁定的實作類別即可。
5. 資料夾結構的演進:從 App 到 Modules
Laravel 預設的 app/Http, app/Models 結構適合中小型網站。但如果你的專案包含「電商」、「部落格」、「論壇」等多個複雜領域,我建議採用 模組化(Modular) 結構。
你可以建立 src/Domains/ECommerce 或 app/Modules/Blog,將相關的 Controller, Model, Policy, Service 都放在同一個領域資料夾下。這就是所謂的 Domain-Driven Design (DDD) 的輕量化實踐。這樣當你要拔除或修改某個功能模組時,不會牽一髮動全身。
6. 相關閱讀與資源延伸
架構優化是一條漫長的路,以下這幾篇文章可以幫助你在 2026 年更好地掌握 Laravel 與系統設計的精髓:
- 肥 Controller 瘦不下來?Laravel 後台架構終極對決:Repository vs. Service vs. Action 模式
- 你的 API 像公共廁所隨便進?Laravel 11 驗證 (Validation) 與 Middleware 客製化終極實戰 (觀念通用于 Laravel 10)
- Laravel 專案從『玩具』變『航母』!資深工程師的『可演化架構』實戰藍圖
老實說,沒有所謂「完美」的架構,只有「適合當下團隊與業務」的架構。但在 Laravel 10 這樣成熟的框架下,遵循 SOLID 原則、善用強型別與自動化測試(別忘了 PHPUnit 或 Pest!),絕對能讓你的工程師生涯少掉很多半夜被叫起來修 Bug 的機會。
你的 Laravel 專案已經變成了難以維護的怪獸嗎? 或者你需要將舊版的 Laravel 10 系統升級並重構為現代化架構?浪花科技擁有豐富的 Laravel 企業級開發經驗,讓我們幫你把技術債變成技術資產。
立即聯繫浪花科技 Eric常見問題
Laravel 專案的 Controller 應該負責哪些事?
為什麼在 Laravel 專案中應該用 DTO 而不是陣列傳遞資料?
Laravel 的 Local Scope 有什麼好處?
2026 年該繼續維護 Laravel 10 舊專案還是直接重寫?
大型 Laravel 專案的資料夾結構該怎麼安排?
訂閱免費電子報
把 AI 自動化、企業系統設計與 WordPress / Laravel 開發的真實案例和可直接照做的技巧,整理成電子報寄給你。只寄精選內容、不灌垃圾信,一鍵就能退訂。