Code 不是能動就好!Laravel Blade 模板終極聖經:寫出讓同事跪著拜讀的優雅程式碼
嗨,我是浪花科技的 Eric。身為一個天天在 Code Sea 裡游泳的工程師,我看過太多讓人血壓飆升的 Blade 檔案了。你以為 Blade 就只是 PHP 混著 HTML 寫嗎?如果你還停留在這個想法,那這篇文章就是你的救贖。我跟你講,一個好的 Blade 模板不只是「能動」,它應該是一首詩、一件藝術品,是能讓三個月後的你、或是接手你專案的同事,看了會流下感動淚水的那種。今天,就讓我這個老司機帶你走一趟 Laravel Blade 的優雅殿堂,從此告別義大利麵式的模板程式碼!
第一章:地基打穩,從佈局(Layout)與結構開始
寫程式跟蓋房子一樣,地基最重要。在 Blade 的世界裡,你的地基就是佈局(Layouts)的規劃。拜託,不要再每個頁面都複製貼上 header 和 footer 了,那根本是石器時代的作法。
1. 善用 @extends, @section, 和 @yield
這是 Blade 最基本也最重要的三劍客。它們定義了你網站的骨架與血肉如何分離。
- @extends(‘layouts.app’): 告訴 Blade:「嘿,這個頁面要繼承
layouts/app.blade.php這個主版型喔!」 - @yield(‘content’): 在主版型中挖一個洞,告訴子頁面:「你的內容就塞到這個叫做 ‘content’ 的洞裡。」
- @section(‘content’): 在子頁面中定義要塞進洞裡的內容。
一個乾淨的主版型應該長這樣:
<!-- resources/views/layouts/app.blade.php -->
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>@yield('title', '浪花科技') - 我們的網站</title>
<!-- Common CSS -->
@stack('styles')
</head>
<body>
@include('partials.header')
<main class="container">
@yield('content')
</main>
@include('partials.footer')
<!-- Common JS -->
@stack('scripts')
</body>
</html>
然後你的子頁面就可以非常清爽:
<!-- resources/views/posts/show.blade.php -->
@extends('layouts.app')
@section('title', $post->title)
@section('content')
<h1>{{ $post->title }}</h1>
<div class="post-body">
{!! $post->body !!}
</div>
@endsection
@push('scripts')
<script src="/js/post-specific-script.js"></script>
@endpush
看到了嗎?完全沒有重複的 HTML 結構,維護起來是不是輕鬆多了?
2. @include vs. 元件(Components):你選對了嗎?
當你的頁面越來越複雜,你會需要把一些區塊拆分出去。這時候 @include 和 @component 就派上用場了。
- @include: 最簡單的引用,把它想像成是單純的複製貼上。適合用在沒有太多邏輯、純粹是靜態內容的區塊,像是頁首、頁尾。
- 元件 (Component): 這是 Laravel 7 之後的王牌。它不僅包含視圖,還可以綁定一個 PHP Class,處理自己的邏輯。這讓你的 UI 元件化,變得可複用、可管理。想像一下一個複雜的「產品卡片」,它需要自己的資料處理邏輯,這時候用 Component 就對了!
簡單來說:無腦小區塊用 @include,需要重複使用且帶有自身邏輯的 UI 元素,請務必使用元件!
第二章:視圖瘦身術,把邏輯留在它該待的地方
這是我最想囉嗦的一點:不要在 Blade 模板裡寫複雜的邏輯! 我看過有人在 .blade.php 檔案裡做資料庫查詢、進行複雜的資料運算…這簡直是場災難!你的 View 就應該是個「笨蛋」,它只負責把 Controller 餵給它的資料漂亮地呈現出來,如此而已。
1. Controller 才是你的大廚
所有資料的準備、篩選、計算,都應該在 Controller 或 Service 層完成。Blade 模板裡最多只該有簡單的 @if, @foreach 迴圈。
錯誤示範(千萬別學):
<!-- 拜託不要這樣寫 -->
@php
$publishedPosts = App\Models\Post::where('is_published', true)->get();
@endphp
@foreach($publishedPosts as $post)
<li>{{ $post->title }}</li>
@endforeach
正確姿勢:
// PostController.php
public function index()
{
$posts = Post::where('is_published', true)->latest()->get();
return view('posts.index', ['posts' => $posts]);
}
<!-- posts/index.blade.php -->
@forelse($posts as $post)
<li>{{ $post->title }}</li>
@empty
<p>目前沒有已發布的文章。</p>
@endforelse
順帶一提,@forelse 是 @foreach 的超進化版,它內建了當資料為空時的處理,讓你的程式碼更乾淨。
2. 自訂你的 Blade 指令(Directives)
當你發現有一些重複的、與呈現相關的 PHP 邏輯時,可以考慮自訂 Blade 指令。例如,格式化金錢。與其在每個地方都寫 number_format($price),不如建立一個 @money 指令。
在 AppServiceProvider 的 boot 方法中加入:
use Illuminate\Support\Facades\Blade;
public function boot()
{
Blade::directive('money', function ($amount) {
return "<?php echo 'NT$ ' . number_format($amount, 0); ?>";
});
}
之後在 Blade 中就可以優雅地使用:
<span class="price">@money($product->price)</span>
第三章:進階黑魔法,效能與維護性的雙重提升
當你掌握了基本功,就可以來點進階的技巧,讓你的專案品質再上一個檔次。
1. View Composers:全局資料的優雅管理者
想像一下,你的網站每個頁面的側邊欄都需要顯示最新的五篇文章。難道你要在每個 Controller 的每個方法裡都去查一次資料庫,然後傳給 View 嗎?當然不是!這時候 View Composer 就是你的救星。
你可以建立一個 ViewServiceProvider,然後在裡面註冊一個 Composer,讓它綁定到特定(或所有)的 View。當這些 View 被渲染時,Composer 會自動執行,並將資料注入進去。
// app/Providers/ViewServiceProvider.php
use Illuminate\Support\Facades\View;
use App\Http\View\Composers\RecentPostsComposer;
public function boot()
{
// 將 Composer 綁定到 'partials.sidebar' 這個視圖
View::composer('partials.sidebar', RecentPostsComposer::class);
}
這樣一來,你的 Controller 就可以專注於處理核心邏輯,而不用分心去管那些共用的邊邊角角的資料了。
2. @push 與 @stack:管理你的 CSS 與 JavaScript
我前面範例已經用到了,這裡特別再強調一次。很多新手會把所有 CSS 和 JS 都塞在主版型裡,導致每個頁面都載入了一大堆根本用不到的資源。@push 和 @stack 就是為了解決這個問題。
- 在主版型的
<head>裡放@stack('styles')。 - 在主版型的
</body>結束前放@stack('scripts')。 - 在需要載入特定資源的子頁面,使用
@push('styles') ... @endpush或@push('scripts') ... @endpush。
這能確保只有在需要的時候才載入對應的資源,對網站效能有直接幫助,也讓資源管理變得井然有序。
結論:寫出讓未來的你感謝自己的程式碼
Laravel Blade 是一個強大且優雅的模板引擎,但工具本身並不能保證產出好的結果。關鍵在於使用它的人的「心法」。
記住幾個核心原則:
- 保持結構清晰:善用佈局繼承和元件化。
- 保持視圖精簡:將所有業務邏輯移出 Blade,讓它專注於呈現。
- 追求可複用性:透過元件、自訂指令來減少重複的程式碼。
- 考慮團隊合作:撰寫乾淨、易於理解的模板,是身為專業工程師的責任。
Code 不只是給機器跑的,更是給人看的。希望今天分享的這些囉哩八唆的觀念,能幫助你打造出更健壯、更易於維護的 Laravel 應用程式。下次當你打開一個 .blade.php 檔案時,希望你會想起這篇文章,寫下讓同事和未來的自己都肅然起敬的優雅程式碼。
延伸閱讀
- 你的 Laravel 專案是技術債炸彈還是傳世藝術品?Laravel 10 專案架構最佳實務指南
- 肥 Controller 瘦不下來?Laravel 後台架構終極對決:Repository vs. Action 模式,資深工程師帶你選對屠龍刀!
- Eloquent 是蜜糖還是毒藥?資深工程師的 Laravel ORM 實戰心法,避開效能地雷區
覺得你的 Laravel 專案架構混亂、效能卡關,或是團隊開發流程需要優化嗎?別再一個人埋頭苦幹了!立即聯繫浪花科技,我們的資深工程師團隊能為你提供專業的架構諮詢、程式碼審查與開發支援,讓我們一起打造出世界級的應用程式!
常見問題 (FAQ)
Q1: Blade 模板中真的完全不能放 PHP 邏輯嗎?
A1: 當然不是完全不行,但原則是「越少越好」。只應該放置與「呈現」直接相關的簡單邏輯,例如 @if 判斷式來決定是否顯示某個元素,或是 @foreach 迴圈來遍歷資料。任何需要計算、查詢、或複雜判斷的業務邏輯,都應該放在 Controller 或更後端的 Service/Repository 層處理完畢,再將最終結果傳給 Blade。
Q2: @include, 元件(Component), 和 @extends 有什麼不同?什麼時候該用哪個?
A2: 這是個好問題!簡單區分:
- @extends: 用於定義頁面的「主骨架」,一個 Blade 檔案通常只會有一個
@extends,用來繼承主版型。 - @include: 用於引入「可重複使用的小區塊」,但這些區塊通常沒有自己的獨立邏輯,像是頁首 (header)、頁尾 (footer)。
- 元件 (Component): 用於建立「可複用且獨立的 UI 單元」,它有自己的視圖和可選的 PHP 類別來處理資料與邏輯。例如:產品卡片、警告訊息框、用戶頭像等。當你需要一個帶有參數和邏輯的 UI 塊時,就該用元件。
Q3: 如何在所有頁面共享特定資料(例如側邊欄的分類列表)?
A3: 最佳解法是使用「View Composers」。你可以在 Service Provider 中註冊一個 View Composer,並將它綁定到你的側邊欄視圖 (e.g., `partials.sidebar`)。這樣一來,每當這個側邊欄被渲染時,View Composer 就會自動執行,從資料庫抓取分類列表並將變數注入到該視圖中。這能避免你在每個 Controller 方法中重複撰寫相同的查詢邏輯,讓程式碼更乾淨 (DRY – Don’t Repeat Yourself)。
Q4: 為什麼要使用 `@push` 和 `@stack` 來管理 CSS/JS?直接寫在主版型不是比較快嗎?
A4: 直接寫在主版型雖然快,但會造成嚴重的效能和維護問題。它會讓每個頁面都載入網站所有的 CSS 和 JS,即使該頁面根本用不到。使用 @push('scripts') 從子頁面將需要的 JS 推送到主版型的 @stack('scripts') 位置,可以確保「按需載入」,只載入當前頁面真正需要的資源。這不僅能加快頁面載入速度,也能讓你的資源管理更有條理,避免未來發生樣式或腳本衝突的惡夢。






