你的 Laravel 專案是技術債炸彈還是傳世藝術品?Laravel 10 專案架構最佳實務指南

2026/01/23 | Laravel技術分享, 全端與程式開發, 架構與效能優化

你的 Laravel 專案是技術債炸彈還是傳世藝術品?Laravel 10 專案架構最佳實務指南

嗨,我是 Eric,浪花科技的資深工程師。如果你跟我一樣在程式碼的海洋裡游了十幾年,你一定聞過那種味道——那種打開一個接手專案時,撲面而來的「陳年義大利麵」味。Controller 裡面塞了 500 行的商業邏輯,Model 模型互相依賴到像個打結的耳機線,View 裡面甚至直接寫了 SQL 查詢(這真的會讓我心臟漏一拍)。

Laravel 是一個非常自由的框架,這也是它的雙面刃。Laravel 10 引入了許多強大的 PHP 8.1+ 特性,如果你還在用 Laravel 5 的思維寫 Laravel 10,那你正在錯過讓專案從「玩具」進化成「企業級應用」的機會。今天,我們不談太高深的微服務拆分,我們來談談在單體式架構(Monolithic)下,如何透過Laravel 10 專案架構最佳實務,把你的程式碼寫得像首詩,而不是一場災難。

1. 擁抱強型別 (Type Hints) 與回傳類型

Laravel 10 的應用程式骨架(Skeleton)已經全面擁抱 PHP 的型別系統。這不是為了裝酷,而是為了讓你的程式碼「剛性」更強,減少那些因為 null 或是錯誤資料型態導致的隱形 Bug。

在 Laravel 10 中,請強迫自己和團隊加上參數型別與回傳型別宣告 (Return Types)。這能讓 IDE 更好地輔助你,也能讓程式碼本身即文件。

不推薦的寫法 (Loose Typing):

public function store($request)
{
    // 這裡的 $request 是什麼? array? Request 物件?
    // 回傳的是什麼? JSON? View?
    // 這種寫法要看完整個 function 才知道在幹嘛
}

Laravel 10 推薦寫法 (Strict Typing):

use Illuminate\Http\RedirectResponse;
use App\Http\Requests\StoreUserRequest;

public function store(StoreUserRequest $request): RedirectResponse
{
    // 清楚知道輸入是有驗證過的 Request,輸出必定是轉址
    $this->userService->create($request->validated());

    return to_route('users.index');
}

2. 拒絕肥大的 Controller:善用 Service Layer 與 Action Pattern

這是我最常嘮叨的一點:「Controller 只是交通警察,不是法官。

Controller 的職責應該僅限於:接收請求、驗證資料(交給 Form Request)、呼叫邏輯層、回傳回應。絕對不要在 Controller 裡面寫複雜的 `if-else` 商業邏輯或是直接操作 Eloquent 的複雜查詢。

在 Laravel 10 中,我們可以更靈活地使用 Service Pattern 或是近年很流行的 Action Pattern (單一職責類別)。

  • Service Pattern: 適合處理一整組相關的邏輯(例如 UserService 包含註冊、更新、刪除)。
  • Action Pattern: 適合單一且複雜的業務邏輯(例如 PublishArticleAction)。

這樣做的好處是,當你以後需要透過 CLI (Artisan Command) 或 API 觸發同樣的邏輯時,你不需要複製貼上程式碼,只要注入這個 Service 或 Action 即可。

3. Form Request 是你的第一道防線

拜託,別再 Controller 裡面寫 $request->validate([...]) 了。這會讓你的 Controller 變得很髒。

使用 Laravel 的 Form Request 功能,將驗證邏輯獨立出來。這不僅讓 Controller 乾淨,還能複用驗證規則。在 Laravel 10 中,你甚至可以在 Form Request 中定義 prepareForValidation 來預處理資料。

// app/Http/Requests/StoreProductRequest.php

public function rules(): array
{
    return [
        'name' => ['required', 'string', 'max:255'],
        'price' => ['required', 'integer', 'min:0'],
        'status' => ['required', Rule::in(ProductStatus::cases())], // 善用 PHP 8.1 Enums
    ];
}

4. 善用 Enums (列舉) 取代魔法數字

如果你的程式碼充滿了 if ($status == 1)if ($type == 'admin'),請立刻停下來。這種「魔法數字」或「魔法字串」是維護的惡夢。

PHP 8.1 引入的 Enum 是 Laravel 10 開發者的好朋友。你可以結合 Laravel 的 Model Casting,讓資料庫存的是整數或字串,但在程式碼中操作的是強型別的 Enum 物件。

// app/Enums/OrderStatus.php
enum OrderStatus: string
{
    case PENDING = 'pending';
    case PAID = 'paid';
    case SHIPPED = 'shipped';
}

// 在 Model 中使用
protected $casts = [
    'status' => OrderStatus::class,
];

// 在程式邏輯中
if ($order->status === OrderStatus::PAID) {
    // 做些什麼
}

5. 模型 (Model) 應該要「瘦」還是「胖」?

這是一個哲學問題。但我建議 Model 應該包含與資料庫交互的邏輯(如 Scopes, Accessors, Mutators, Relations),但不應該包含「商業流程邏輯」。

善用 Local Scopes 來封裝常用的查詢條件,讓你的查詢語句像英文句子一樣易讀。

糟糕的查詢寫法:

$users = User::where('active', 1)
             ->where('created_at', '>', now()->subDays(7))
             ->orderBy('created_at', 'desc')
             ->get();

優雅的 Scope 寫法:

// User Model 內定義 Scope
public function scopeActive(Builder $query): void { ... }
public function scopeRecent(Builder $query): void { ... }

// 使用時
$users = User::active()->recent()->get();

6. 依賴注入 (Dependency Injection) vs. Facades

Laravel 的 Facades (如 File::put(), Route::get()) 非常方便,但也常被批評難以測試。雖然 Laravel 10 的 Facades 其實很容易 Mock,但在編寫核心商業邏輯(Service/Action)時,我更推薦使用 Constructor Injection (建構子注入)

這能清楚地列出該類別的依賴關係,並利用 PHP 8 的 Constructor Property Promotion 讓程式碼更簡潔。

class ProcessOrderAction
{
    public function __construct(
        protected PaymentGateway $payment,
        protected InventoryService $inventory
    ) {}

    public function execute(Order $order)
    {
        // ...
    }
}

結論:架構是為了未來的自己

寫程式最爽的時刻不是寫完的那一刻,而是三個月後你回來看這段程式碼,發現你依然看得懂,而且能在一分鐘內加上新功能。Laravel 10 提供了非常棒的工具讓我們實踐 Clean Code,重點在於你是否願意在初期多花一點時間去設計架構。

別讓你的專案變成技術債炸彈,從今天開始重構吧!

常見問題 (FAQ)

Q1: Repository Pattern 在 Laravel 10 中還是必要的嗎?

這取決於專案規模。對於中小型專案,直接使用 Eloquent Model 通常就足夠高效且直觀。Repository Pattern 往往會增加不必要的抽象層。除非你有明確需求(例如未來可能更換資料庫,或需要極度嚴格的單元測試隔離),否則 Service Layer 搭配 Eloquent 通常是更現代且實用的選擇。

Q2: Action Pattern 和 Service Pattern 我該選哪一個?

沒有標準答案。如果你的業務邏輯非常單一且明確(例如:「發送歡迎信」),Action Pattern (Single Class) 非常適合。如果是一組相關的操作(例如:「使用者管理」包含 CRUD),Service Pattern 將這些方法群組起來會比較好管理。許多大型專案會混合使用兩者。

Q3: 既有的大型舊專案如何導入這些最佳實務?

不要試圖一次重寫!採用「童子軍原則」:每次修改檔案時,讓它比你發現時更乾淨一點。從新功能開始採用新架構,對於舊程式碼則在需要維護時逐步重構。例如,先將一段寫在 Controller 的邏輯抽取成 Action,慢慢改善整體體質。

延伸閱讀

不想讓你的 Laravel 專案變成難以維護的怪獸?

無論是架構規劃、效能優化,還是技術債重構,浪花科技的資深團隊都能為您提供最專業的技術支援。讓我們幫您打造穩固、可擴展的數位基石。

立即填寫表單聯繫我們

 
立即諮詢,索取免費1年網站保固