Code 不是能動就好!Laravel Blade 模板終極聖經:寫出讓同事愛不釋手的優雅程式碼

2025/08/22 | Laravel技術分享

Code 不是能動就好!Laravel Blade 模板終極聖經:寫出讓同事愛不釋手的優雅程式碼

嗨,我是浪花科技的 Eric。身為一個每天在程式碼大海裡打滾的資深工程師,我看過太多令人「驚嘆」的 Blade 模板了。有些模板裡的邏輯比 Controller 還複雜,有些則是重複的程式碼像複製貼上軍團一樣,遍佈在專案的各個角落。每次接手這種專案,心裡都只有一個念頭:「施主,你累了嗎?」

說真的,Laravel 的 Blade 模板引擎非常強大且優雅,它的出現是為了解決 PHP 混雜 HTML 的「義大利麵式程式碼 (Spaghetti Code)」地獄。但好的工具也要用對方法,否則再鋒利的寶劍也只會變成一把鈍刀。今天,我就來囉嗦一下,分享一些我多年來整理的 Laravel Blade 模板最佳實務,從基礎心法到進階黑魔法,目標是讓你的 View 程式碼不只能動,還要動得漂亮,讓接手的同事對你肅然起敬!

打穩地基:View 的核心原則——「專心做好一件事」

在我們深入探討各種 Blade 指令之前,有個最重要的觀念一定要先刻在腦子裡:View 的唯一職責就是「呈現資料」,而不是「處理邏輯」。這就跟軟體工程的「單一職責原則 (Single Responsibility Principle)」一樣。

View 層該做與不該做的事

一個乾淨的 Blade 模板應該像個專職的化妝師,你給他什麼素材(資料),他就負責畫出漂亮的妝容(HTML 頁面),而不是自己跑去調配化妝品(處理業務邏輯)。

  • 該做的事:
    • 使用迴圈(@foreach)來迭代陣列並顯示列表。
    • 使用條件判斷(@if)來決定是否顯示某個區塊。
    • 呼叫簡單的輔助函式(Helper Function)來格式化資料,例如:{{ $post->created_at->format('Y-m-d') }}
    • 將傳入的變數忠實地渲染到 HTML 上。
  • 絕對不該做的事:
    • 在 Blade 檔案裡直接下資料庫查詢,例如:{{ App\Models\User::find(1)->name }}。看到這個我真的會吐血,這是天大的禁忌!
    • 進行複雜的資料運算或業務邏輯判斷。這些應該在 Controller 或 Service 層就處理好。
    • 定義函式或類別。

記住,當你發現自己想在 .blade.php 檔案裡寫超過三行的 PHP 邏輯時,請停下來,深呼吸,然後問自己:「這段邏輯是不是應該放在更早的地方處理?」十之八九,答案都是肯定的。

告別複製貼上地獄:模板繼承與組件化的藝術

寫程式最忌諱的就是重複。在前端模板中,我們有大量的共用區塊,像是 header、footer、sidebar 等。Blade 提供了兩種絕佳的武器來消滅重複的程式碼。

傳統王者:`@extends`, `@section`, `@yield`

這是最經典的模板繼承方式,透過一個主佈局 (layout) 檔案來定義網站的骨架,然後讓各個頁面去繼承並填入內容。

首先,建立一個主佈局檔案 resources/views/layouts/app.blade.php

<!DOCTYPE html>
<html>
<head>
    <title>@yield('title', '我的網站')</title>
</head>
<body>
    <div class="container">
        @yield('content')
    </div>
</body>
</html>

然後,在你的頁面模板中,例如 resources/views/pages/home.blade.php,可以這樣繼承:

@extends('layouts.app')

@section('title', '首頁')

@section('content')
    <h1>歡迎來到首頁</h1>
    <p>這是頁面主要內容。</p>
@endsection

這種方式結構清晰,非常適合用來定義整個網站的大框架。

現代化的選擇:擁抱組件 (Components)

當你的網頁元件(例如:警告訊息、卡片、按鈕)需要在多個地方重複使用時,「組件」就是你的救星。Laravel 7 之後引入了更強大的 Class-based Components,讓組件化開發變得更加優雅。

我們可以透過 Artisan 指令快速建立一個組件:

php artisan make:component Alert

這會產生兩個檔案:app/View/Components/Alert.phpresources/views/components/alert.blade.php

alert.blade.php 中定義組件的 HTML 結構:

<!-- resources/views/components/alert.blade.php -->
<div class="alert alert-{{ $type }}">
    {{ $slot }}
</div>

Alert.php 中可以定義組件需要的屬性與邏輯:

<?php

namespace App\View\Components;

use Illuminate\View\Component;

class Alert extends Component
{
    public $type;

    public function __construct($type = 'info')
    {
        $this->type = $type;
    }

    public function render()
    {
        return view('components.alert');
    }
}

這樣,在任何 Blade 檔案中,你都可以像使用 HTML 標籤一樣呼叫它:

<x-alert type="danger">
    這是一則重要的錯誤訊息!
</x-alert>

<x-alert type="success">
    操作成功!
</x-alert>

看到了嗎?這種方式不僅讓你的模板變得極度乾淨,也把元件相關的邏輯完美地封裝在對應的 PHP Class 中,這才是高內聚、低耦合的專業寫法!

進階黑魔法:讓你的 Blade 模板更上一層樓

掌握了基礎,我們來看看一些能讓你開發效率起飛的進階技巧。

`@include`, `@each` 與 `@includeWhen`

@include 用來載入一個子視圖 (partial view),非常適合用來拆分複雜的頁面。

@include('partials.header')

當你需要渲染一個陣列時,別再傻傻地用 @foreach 搭配 @include@each 才是更簡潔的寫法:

// posts 是一個文章物件的集合
// 'partials.post' 是單一文章的顯示模板
@each('partials.post', $posts, 'post', 'partials.no-posts')
// 第四個參數是當 $posts 為空時要顯示的模板,超方便!

@includeWhen 則可以根據條件決定是否載入子視圖,讓你的判斷式更語意化。

@includeWhen($user->isAdmin(), 'admin.dashboard', ['user' => $user])

`@stack` 與 `@push`:動態注入 CSS/JS 的救星

你有沒有遇過這種情況:主佈局檔案載入了全站共用的 JS,但某個特定頁面需要額外載入一個專屬的 JS 檔案?這時候 @push@stack 就派上用場了。

在主佈局檔案 layouts/app.blade.php 的 `</body>` 前面加上:

    @stack('scripts')
</body>

然後在你的子頁面中,可以這樣把 script推進去:

@push('scripts')
    <script src="/path/to/my/page-specific-script.js"></script>
@endpush

這樣就能優雅地管理頁面專屬的資源,而不用把主佈局檔案搞得亂七八糟。

效能與安全:工程師的最後一道防線

優雅的程式碼不僅是好看,更要兼顧效能與安全。

效能優化:View Composers 的妙用

如果你的網站每個頁面的 sidebar 都需要顯示最新的五篇文章,你該怎麼做?在每個 Controller 的每個方法裡都去查一次資料庫,然後傳給 View 嗎?拜託不要!

View Composers 就是為了解決這種「跨多個 View 的共用資料」問題而生的。你可以在 `AppServiceProvider` 中定義一個 Composer:

use Illuminate\Support\Facades\View;
use App\Models\Post;

public function boot()
{
    // 當 'layouts.sidebar' 這個 view 被渲染時,自動綁定 $latestPosts 變數
    View::composer('layouts.sidebar', function ($view) {
        $view->with('latestPosts', Post::latest()->take(5)->get());
    });
}

這樣一來,你就不用在任何 Controller 裡手動傳遞 $latestPosts 了,Blade 會自動搞定。這不僅簡化了 Controller,也讓資料來源更集中,方便管理。

安全性:別讓 XSS 攻擊毀了你的網站

Laravel 的 Blade 預設是相當安全的。當你使用 `{{ $variable }}` 語法時,它會自動對內容進行 HTML 實體編碼,有效防止跨站腳本攻擊 (XSS)。

但有時候你可能真的需要輸出未經編碼的 HTML(例如:從後台富文本編輯器來的內容)。這時候你可以用 `{!! $variable !!}`。但請務必記住,你必須 100% 確保 `{!! !!}` 裡的內容是安全、可信的。通常我們會搭配 HTML Purifier 這類的套件,先過濾掉惡意程式碼後再輸出。

總結來說,Laravel Blade 模板最佳實務的核心精神就是:職責分離、保持簡潔、擁抱組件化。一個好的模板,應該是連不懂後端的前端工程師都能輕鬆看懂並修改的。把邏輯留在後端,讓 Blade 專心扮演好它「化妝師」的角色。下次當你又想在 Blade 裡寫複雜邏輯時,請記得我今天這番工程師的囉嗦吧!


延伸閱讀

希望這篇文章能幫助你寫出更優雅、更專業的 Blade 模板。如果你在 Laravel 開發上遇到了任何瓶頸,或是需要專業的技術顧問服務,浪花科技的團隊隨時準備好為你提供協助。我們不只會寫 Code,更專注於打造穩固、可擴展且易於維護的系統架構。

👉 立即聯繫浪花科技,讓我們一起打造下一個偉大的專案!

常見問題 (FAQ)

Q1: `@extends` 佈局繼承和 `@component` 組件化有什麼主要區別?我該如何選擇?

A1: 這是一個很好的問題!`@extends` 主要用於定義「頁面級」的大框架或骨架,例如整個網站共用的 header, footer, sidebar。它是一種由上而下(父模板定義框架,子模板填空)的繼承關係。而 `@component` 則是用於建立「可重複使用的 UI 元件」,例如按鈕、警告框、卡片等。它是更小、更獨立的單位,可以像積木一樣在任何頁面中組合使用。簡單來說:用 `@extends` 處理頁面佈局,用 `@component` 處理頁面內的元件。

Q2: 什麼時候我才應該使用 `{!! !!}` 來輸出未經編碼的 HTML?

A2: 只有在你「完全信任」資料來源,並且「必須」輸出 HTML 標籤時才使用。最常見的例子就是後台的所見即所得(WYSIWYG)編輯器產生的內容。但即便是這種情況,最佳實踐是在儲存或輸出前,使用像 `HTML Purifier` 這樣的函式庫對 HTML 內容進行嚴格的過濾和清理,只允許安全的標籤和屬性通過,以防止惡意的 JavaScript 或 CSS 注入,從而杜絕 XSS 攻擊的風險。總之,非必要,絕不用。

Q3: 在 Blade 檔案中放入一些 if-else 判斷是壞習慣嗎?

A3: 不完全是。簡單的顯示邏輯判斷是完全可以接受的。例如 `if ($user->isActive())` 來決定是否顯示某個按鈕,或是 `foreach ($posts as $post)` 來迭代文章列表。這些都屬於「呈現邏輯」的範疇。壞習慣是指在 Blade 中放入「業務邏輯」,例如 `if ($user->order_count > 10 && $user->created_at < now()->subYear())` 這種複雜的條件判斷。這種邏輯應該在 Controller 或 Service 層處理好,然後只傳一個簡單的布林值(如 `$isVipUser`)給 View,讓 View 的判斷保持單純:`@if ($isVipUser)`。

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