> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Blade 模板

> 解說 Laravel 模板引擎「Blade」的基本語法、條件判斷、迴圈與版面繼承。

## 前言

Blade 是 Laravel 內建的、簡潔卻強大的模板引擎。
與部分 PHP 模板引擎不同，Blade 不會限制在模板中使用原生 PHP 程式碼。
所有 Blade 模板都會被編譯為 PHP 並快取，因此 Blade 幾乎不會對應用程式帶來額外負擔。

Blade 模板檔案的副檔名為 `.blade.php`，通常存放於 `resources/views` 目錄。

### Blade 編譯流程

以下顯示 `.blade.php` 檔案如何被轉為 HTML 回應。一旦編譯完成的檔案會被快取，同一模板第 2 次以後的請求便會跳過編譯。

```mermaid theme={null}
flowchart LR
    A[".blade.php 檔案"] --> B{"是否有快取?"}
    B -->|"Yes"| C["使用快取的 PHP"]
    B -->|"No"| D["Blade Compiler"]
    D --> E["轉為 PHP 程式碼"]
    E --> F["存至 storage/framework/views/"]
    F --> G["執行 PHP"]
    C --> G
    G --> H["HTML 回應"]
```

```php theme={null}
Route::get('/', function () {
    return view('greeting', ['name' => '太郎']);
});
```

## 顯示資料

要顯示傳入 Blade 視圖的資料，可用雙大括號包住變數。

```blade theme={null}
你好，{{ $name }}。
```

<Info>
  Blade 的 `{{ }}` 會自動透過 PHP 的 `htmlspecialchars` 函式進行處理以防止 XSS 攻擊。
</Info>

除了變數，也可以顯示 PHP 函式的結果。

```blade theme={null}
目前的 UNIX 時間戳：{{ time() }}
```

### 顯示未跳脫的資料

若希望略過跳脫，可使用 `{!! !!}` 語法。

```blade theme={null}
你好，{!! $name !!}。
```

<Warning>
  在顯示使用者輸入的資料時，請務必使用 `{{ }}` 讓自動跳脫生效。
  對不受信任的輸入使用 `{!! !!}` 會導致 XSS 漏洞。
</Warning>

### 與 JavaScript 框架共存

若 JavaScript 框架也使用大括號，可用 `@` 符號讓 Blade 略過該處的渲染。

```blade theme={null}
<h1>Laravel</h1>

你好，@{{ name }}。
```

此時 Blade 會移除 `@`，但 `{{ name }}` 會原樣傳送到瀏覽器，由 JavaScript 框架負責渲染。

<Info>
  想比較以 Blade 為主，或擴展到 Livewire、Inertia 時的選擇，請參閱[前端](/zh-TW/frontend)。
</Info>

## Blade 指令

### 條件判斷（if 敘述）

```blade theme={null}
@if (count($records) === 1)
    有 1 筆紀錄。
@elseif (count($records) > 1)
    有多筆紀錄。
@else
    沒有紀錄。
@endif
```

使用 `@unless` 可撰寫「若不是……」的條件。

```blade theme={null}
@unless (Auth::check())
    未登入。
@endunless
```

若要確認變數是否已定義且非 null，可用 `@isset` 與 `@empty`。

```blade theme={null}
@isset($records)
    // $records 已定義且非 null 時
@endisset

@empty($records)
    // $records 為「空」時
@endempty
```

### 認證指令

```blade theme={null}
@auth
    // 已認證使用者的內容
@endauth

@guest
    // 未認證使用者的內容
@endguest
```

### Switch 敘述

```blade theme={null}
@switch($i)
    @case(1)
        第一種情況...
        @break

    @case(2)
        第二種情況...
        @break

    @default
        預設情況...
@endswitch
```

### 迴圈

Blade 提供處理迴圈的便利指令。

```blade theme={null}
@for ($i = 0; $i < 10; $i++)
    目前的值：{{ $i }}
@endfor

@foreach ($users as $user)
    <p>使用者：{{ $user->name }}</p>
@endforeach

@forelse ($users as $user)
    <li>{{ $user->name }}</li>
@empty
    <p>沒有使用者</p>
@endforelse

@while (true)
    <p>會永遠迴圈。</p>
@endwhile
```

在迴圈內可使用 `@break` 與 `@continue` 控制迴圈。

```blade theme={null}
@foreach ($users as $user)
    @if ($user->type == 1)
        @continue
    @endif

    <li>{{ $user->name }}</li>

    @if ($user->number == 5)
        @break
    @endif
@endforeach
```

也可以將條件直接傳給指令。

```blade theme={null}
@foreach ($users as $user)
    @continue($user->type == 1)

    <li>{{ $user->name }}</li>

    @break($user->number == 5)
@endforeach
```

### 迴圈變數

在 `@foreach` 迴圈中，可透過 `$loop` 變數取得關於迴圈的資訊。

```blade theme={null}
@foreach ($users as $user)
    @if ($loop->first)
        這是第一次迭代。
    @endif

    @if ($loop->last)
        這是最後一次迭代。
    @endif

    <p>使用者：{{ $user->name }}</p>
@endforeach
```

| 屬性                 | 說明                |
| ------------------ | ----------------- |
| `$loop->index`     | 目前迴圈的索引（從 0 開始）   |
| `$loop->iteration` | 目前迴圈的迭代次數（從 1 開始） |
| `$loop->remaining` | 剩餘的迭代次數           |
| `$loop->count`     | 陣列的元素數量           |
| `$loop->first`     | 是否為第一次迭代          |
| `$loop->last`      | 是否為最後一次迭代         |
| `$loop->even`      | 是否為偶數次迭代          |
| `$loop->odd`       | 是否為奇數次迭代          |
| `$loop->depth`     | 目前迴圈的巢狀深度         |
| `$loop->parent`    | 若為巢狀迴圈，則為父層迴圈的變數  |

## 註解

Blade 註解不會出現在渲染後的頁面中。

```blade theme={null}
{{-- 這則註解不會出現在渲染後的 HTML 中 --}}
```

## 版面

### 使用元件的版面

Laravel 建議使用 Blade 元件來建構版面。

首先建立版面元件。

```blade theme={null}
<!-- resources/views/components/layout.blade.php -->
<html>
    <head>
        <title>{{ $title ?? '應用程式名稱' }}</title>
    </head>
    <body>
        <header>
            <nav>
                <!-- 導覽列 -->
            </nav>
        </header>

        <main>
            {{ $slot }}
        </main>
    </body>
</html>
```

接著建立使用該版面的視圖。

```blade theme={null}
<!-- resources/views/dashboard.blade.php -->
<x-layout>
    <x-slot:title>儀表板</x-slot>

    <h1>儀表板</h1>
    <p>歡迎！</p>
</x-layout>
```

### 使用模板繼承的版面

作為傳統做法，也可以使用 `@extends`、`@section`、`@yield` 進行模板繼承。

```mermaid theme={null}
flowchart TD
    A["子視圖<br>@extends('layouts.app')"] --> B["父版面<br>layouts/app.blade.php"]
    A --> C["@section('title', '子頁面')"]
    A --> D["@section('content')<br>內容本體<br>@endsection"]
    B --> E["@yield('title')<br>← 嵌入 title"]
    B --> F["@yield('content')<br>← 嵌入 content"]
    C --> E
    D --> F
    E --> G["最終 HTML"]
    F --> G
```

**父版面的定義：**

```blade theme={null}
<!-- resources/views/layouts/app.blade.php -->
<html>
    <head>
        <title>應用程式名稱 - @yield('title')</title>
    </head>
    <body>
        @section('sidebar')
            預設側邊欄
        @show

        <div class="container">
            @yield('content')
        </div>
    </body>
</html>
```

**子視圖繼承版面：**

```blade theme={null}
<!-- resources/views/child.blade.php -->
@extends('layouts.app')

@section('title', '子頁面')

@section('sidebar')
    @parent

    <p>要加入側邊欄的內容</p>
@endsection

@section('content')
    <p>內容本體</p>
@endsection
```

<Info>
  使用 `@parent` 可保留父版面 `@section` 的內容並在其後追加。
</Info>

## 子視圖引入

使用 `@include` 指令可將某個 Blade 視圖嵌入其他視圖中。
父視圖中可用的所有變數，在被引入的視圖中也可以使用。

```blade theme={null}
<div>
    @include('shared.errors')

    <form>
        <!-- 表單內容 -->
    </form>
</div>
```

也可以額外傳入變數。

```blade theme={null}
@include('view.name', ['status' => 'complete'])
```

## 表單的 CSRF 保護

在 `web` 路由檔中，送出 `POST`、`PUT`、`PATCH`、`DELETE` 請求的 HTML 表單，請務必加上 `@csrf` 指令。

```blade theme={null}
<form method="POST" action="/profile">
    @csrf

    <!-- 表單欄位 -->
</form>
```

若要從表單送出 `PUT`、`PATCH`、`DELETE` 請求，可使用 `@method` 指令。

```blade theme={null}
<form method="POST" action="/post/1">
    @csrf
    @method('DELETE')

    <button type="submit">刪除</button>
</form>
```

<Info>
  關於 Origin 驗證與包含 `X-CSRF-TOKEN` / `X-XSRF-TOKEN` 標頭在內的正式 CSRF 對策，請參閱 [CSRF 保護](/zh-TW/csrf)。
</Info>

## 總結

以下整理 Blade 模板引擎的主要功能。

<AccordionGroup>
  <Accordion title="顯示資料">
    `{{ $variable }}` 為附帶跳脫的顯示；`{!! $variable !!}` 為未跳脫的顯示。
  </Accordion>

  <Accordion title="條件判斷">
    `@if`、`@elseif`、`@else`、`@endif`、`@unless`、`@isset`、`@empty`、`@auth`、`@guest`。
  </Accordion>

  <Accordion title="迴圈">
    `@for`、`@foreach`、`@forelse`、`@while` 與利用 `$loop` 變數的控制。
  </Accordion>

  <Accordion title="版面">
    元件式（`<x-layout>` 與 `{{ $slot }}`）或模板繼承（`@extends`、`@section`、`@yield`）。
  </Accordion>

  <Accordion title="子視圖">
    使用 `@include` 將視圖作為可重用零件嵌入。
  </Accordion>
</AccordionGroup>


## Related topics

- [什麼是 Laravel](/zh-TW/introduction.md)
- [授權（Gate 與 Policy）](/zh-TW/authorization.md)
- [安裝](/zh-TW/installation.md)
- [認證入門](/zh-TW/authentication.md)
- [Laravel LSP — 以 Language Server Protocol 擴充 IDE 功能](/zh-TW/blog/laravel-lsp-introduction.md)
