> ## 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.php` 扩展名，通常存放在 `resources/views` 目录下。

### Blade 编译流程

下图展示 `.blade.php` 文件如何被转换为 HTML 响应。文件一旦编译就会被缓存，因此同一模板的第二次及以后的请求会跳过编译。

```mermaid theme={null}
flowchart LR
    A[".blade.php 文件"] --> B{"缓存是否存在？"}
    B -->|"是"| C["使用已缓存的 PHP"]
    B -->|"否"| D["Blade 编译器"]
    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/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)
        第 1 个分支...
        @break

    @case(2)
        第 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>
  实际运维中的 CSRF 保护，包括 Origin 校验、`X-CSRF-TOKEN` / `X-XSRF-TOKEN` 头等，请参阅 [CSRF 保护](/zh/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

- [邮件发送](/zh/mail.md)
- [使用 Vite 打包资源](/zh/vite.md)
- [Laravel Pennant](/zh/pennant.md)
- [什么是 Laravel](/zh/introduction.md)
- [视图](/zh/views.md)
