告別 View 層義大利麵:Laravel Blade 現代化架構與 Component 實戰
您的 View 層是否也充滿了難以維護的「義大利麵程式碼」?資深工程師 Eric 帶您深入解析 Laravel Blade 的三大病灶,並指出邏輯外洩是維護性低落的主因。本指南強調擁抱現代化的 Blade Component(<x-component>)以取代傳統的 @include,並教您如何將複雜邏輯移出 View 層,徹底實踐純淨架構。立即學習 Laravel 11 的 @use 和 @class 等新指令,將您的專案從技術債深淵中拯救出來!從今天開始重構,大幅提升程式碼可讀性與開發效率!
拒絕 View 層義大利麵!Laravel 11 Blade 模板現代化架構與 Component 實戰指南
嗨,我是 Eric,浪花科技的資深工程師。今天我要來聊聊一個讓許多 Laravel 開發者(尤其是剛從這坑跳進來的)又愛又恨的主題:Blade 模板。
上週我在幫一位新進工程師 Code Review 時,打開了一個 index.blade.php,當場差點心肌梗塞。為什麼?因為我在這份「View」檔案裡看到了複雜的資料庫查詢、未經處理的 PHP 原生陣列操作,還有巢狀了五層的 if-else 判斷式。這不是 View,這是義大利麵(Spaghetti Code),而且是放了三天糊成一團的那種。
很多人認為 Blade 只是拿來「顯示 HTML」的,所以隨便寫沒關係。錯!大錯特錯!一個維護性高的 Laravel 專案,View 層的架構整潔度,絕對不亞於後端的 Service 或 Repository。隨著 Laravel 11 的發布,Blade 已經演化成一個強大的元件化(Component-based)系統。
今天這篇文章,我要把多年的血淚經驗濃縮成這篇「Laravel Blade 模板最佳實務」,教你如何寫出優雅、可維護,且符合現代化開發標準的 View。
為什麼你的 Blade 總是亂七八糟?常見的三大病灶
在進入技術細節前,我們先來診斷一下,你的 Blade 是否患了以下幾種常見疾病:
- 邏輯外洩 (Logic Leaking): 在 Blade 裡面寫 Eloquent Query (
User::where(...)->get())。這是大忌!View 應該只負責「呈現」,不負責「思考」。 - 過度依賴 @include: 雖然
@include很好用,但它無法很好地處理資料作用域(Scope)和屬性傳遞,導致子視圖變得難以預測。 - 複製貼上魔人: 按鈕、表單輸入框、卡片樣式在每個檔案都重寫一遍,只要設計師一改 UI,全公司工程師都要加班改 Code。
1. 擁抱 Component (元件),拋棄 @include
如果你還在大量使用 @include('partials.header'),現在是時候改變習慣了。從 Laravel 7 開始引入的 Blade Components (x-components) 才是現代化的標準寫法。
為什麼 Component 比較好?
Component 允許你像寫 HTML 標籤一樣使用你的元件,並且提供了強大的屬性包(Attribute Bag)功能,這讓你的程式碼語意更清晰。
傳統 @include 寫法(容易混亂):
{{-- 參數傳遞不明確,無法強制型別 --}}
@include('components.button', ['type' => 'primary', 'text' => '送出表單'])
現代 Component 寫法(語意清晰):
<!-- 看起來就像原生 HTML,支援 Slot 和預設屬性合併 -->
<x-button type="primary" class="mt-4">
送出表單
</x-button>
實戰:建立一個可複用的 Alert 元件
我們可以使用 Artisan 指令快速建立元件:
php artisan make:component Alert --view
接著在 resources/views/components/alert.blade.php 中:
@props(['type' => 'info'])
@php
$colors = [
'info' => 'bg-blue-100 text-blue-800',
'error' => 'bg-red-100 text-red-800',
'success' => 'bg-green-100 text-green-800',
];
$classes = $colors[$type] ?? $colors['info'];
@endphp
<div {{ $attributes->merge(['class' => "p-4 rounded-lg $classes"]) }}>
{{ $slot }}
</div>
Eric 的囉嗦重點: 注意那個 $attributes->merge()。這是 Component 最強大的功能之一,它允許你在呼叫元件時傳入額外的 CSS class(例如 mb-4),並自動與元件預設的 class 合併。如果你用 @include,這功能你得自己手刻到天荒地老。
2. 保持 View 層純淨:Logic 應該在哪裡?
這是我最常強調的一點:View 不應該包含複雜的商業邏輯。
如果你發現自己在 Blade 裡寫了大量的 @php 區塊來處理資料轉換,請停下來。你有幾個更好的選擇:
選項 A:Accessor (存取器) 與 Presenter
如果是簡單的資料格式化(例如日期、金額),請在 Model 使用 Accessor,或者使用 Laravel 的 API Resource / Presenter 模式。
選項 B:View Models (視圖模型)
當頁面邏輯非常複雜時(例如儀表板),Controller 傳給 View 的變數會變得雜亂無章。這時可以考慮 View Model 模式。這不是 Laravel 內建的,但這是一個非常棒的 Design Pattern。
// 糟糕的寫法:在 Blade 裡面算數學
Total: {{ $order->items->sum(fn($item) => $item->price * $item->quantity) * 1.05 }}
// 優雅的寫法:Model 或 Presenter 處理好
Total: {{ $order->total_with_tax }}
3. Laravel 11 新特性:更簡潔的 Blade
隨著 Laravel 10 和 11 的推進,Blade 也變得更聰明了。有一個經常被忽略但極好用的 Directive:@use。
以前如果你要在 Blade 裡使用某些 Enum 或 Class 常數,你可能需要傳入 View,或者寫完整的 Namespace:
{{-- 舊寫法 --}}
@if($user->status === \App\Enums\UserStatus::ACTIVE)
<span>啟用中</span>
@endif
現在,你可以直接使用 @use,讓程式碼更乾淨:
{{-- Laravel 10/11 新寫法 --}}
@use('App\Enums\UserStatus')
@if($user->status === UserStatus::ACTIVE)
<span>啟用中</span>
@endif
4. 效能優化:別在迴圈裡埋地雷
Blade 的效能問題通常源自於資料庫查詢的 N+1 問題。雖然這主要是在 Controller 層解決(使用 Eager Loading with()),但在 Blade 層也有防守的方式。
避免在 Blade 呼叫關聯關係:
千萬不要在 @foreach 迴圈中呼叫類似 $user->posts()->count() 的方法。因為 () 會觸發新的 SQL Query。如果一定要用,請確保你在 Controller 已經用 withCount('posts') 載入過了。
善用 @class 與 @style:
這不是效能優化,而是開發效率優化。不要再寫醜陋的三元運算子來決定 CSS Class 了。
{{-- 舊寫法:難以閱讀 --}}
<div class="p-4 {{ $isActive ? 'bg-blue-500' : 'bg-gray-200' }}">...</div>
{{-- 新寫法:條件式 Class --}}
<div @class([
'p-4',
'bg-blue-500' => $isActive,
'bg-gray-200' => ! $isActive,
])>
...
</div>
5. Eric 的 Blade Code Review 檢查清單
最後,身為資深工程師,我幫大家整理了一份檢查清單。下次 Commit 程式碼前,請先自我檢查:
- [ ] 是否使用了
<x-component>而不是@include? - [ ] Blade 檔案中是否沒有任何
Model::query()資料庫查詢? - [ ] 是否移除了複雜的 PHP 邏輯運算,改由 Controller 或 Accessor 提供?
- [ ] 是否使用了
@forelse來優化空資料的顯示,而不是@if($items->count() > 0) ... @foreach? - [ ] 巢狀迴圈是否超過 3 層?如果是,請考慮拆分成子元件 (Sub-components)。
- [ ] 你的 Layout 是否使用了 Component Layout (
<x-app-layout>) 而不是舊式的@extends?(這也是現代 Laravel 的推薦做法)
結論:好的 Blade 讓你下班早回家
Blade 模板不僅僅是 HTML 的容器,它是你應用程式呈現層的靈魂。透過 Component 架構、邏輯分離以及善用 Laravel 11 的新語法,你的 View 層將不再是難以維護的義大利麵,而是結構嚴謹的積木城堡。
技術債這種東西,是會有複利的。今天偷懶寫在 View 裡的邏輯,下個月就會變成你加班的理由。從今天開始,善待你的 Blade 吧!
如果你在 Laravel 架構設計上遇到瓶頸,或是想要針對既有的專案進行效能健檢與重構,歡迎隨時聯繫我們。
延伸閱讀
- 肥 Controller 瘦不下來?Laravel 後台架構終極對決:Repository vs. Service vs. Action 模式
- 前後端分離還是大一統?Laravel + Vue / React 整合全攻略
- Eloquent 是蜜糖還是毒藥?資深工程師的 Laravel ORM 實戰心法
常見問題 (FAQ)
Q1: 已經有很多舊的 @include 程式碼,需要全部重構成 Component 嗎?
不必急著一次全部重構。Eric 建議採用「童子軍法則」:當你需要修改某個舊檔案,或者開發新功能時,再順手將相關的部份重構為 Component。漸進式改進比大規模重寫風險更低。
Q2: Blade 跟 Vue.js / React 該怎麼選擇?
如果你的應用程式互動性不高(主要是展示資訊、簡單表單),Blade + Alpine.js 是開發速度最快且 SEO 最好的組合。如果你需要高度互動的 SPA(單頁應用)體驗,或者複雜的狀態管理,那麼 Laravel + Vue/React (透過 Inertia.js 或 API) 會是更好的選擇。
Q3: 在 Blade 裡面使用 @php … @endphp 真的很糟嗎?
少量的變數賦值是可以接受的(例如設定 Component 的 class 樣式)。但如果是進行資料庫查詢、API 呼叫或複雜的陣列處理,絕對是 Bad Practice。這些邏輯應該在 Controller、Service 或 View Model 中完成。






