Blade 模板
简介
Blade 是 Laravel 包含的简单而强大的模板引擎。与某些 PHP 模板引擎不同,Blade 不限制您在模板中使用纯 PHP 代码。实际上,所有 Blade 模板都被编译成纯 PHP 代码并缓存,直到它们被修改,这意味着 Blade 实际上为您的应用程序增加了零开销。Blade 模板文件使用 .blade.php
文件扩展名,通常存储在 resources/views
目录中。
Blade 视图可以从路由或控制器中使用全局 view
辅助函数返回。当然,正如 视图 文档中提到的,可以使用 view
辅助函数的第二个参数将数据传递给 Blade 视图
1Route::get('/', function () {2 return view('greeting', ['name' => 'Finn']);3});
使用 Livewire 增强 Blade
想要将您的 Blade 模板提升到一个新的水平,并轻松构建动态界面吗?请查看 Laravel Livewire。Livewire 允许您编写 Blade 组件,这些组件通过动态功能进行增强,这些功能通常只能通过前端框架(如 React 或 Vue)实现,从而提供了一种构建现代、响应式前端的好方法,而无需许多 JavaScript 框架的复杂性、客户端渲染或构建步骤。
显示数据
您可以通过将变量包裹在花括号中来显示传递给 Blade 视图的数据。例如,给定以下路由
1Route::get('/', function () {2 return view('welcome', ['name' => 'Samantha']);3});
您可以像这样显示 name
变量的内容
1Hello, {{ $name }}.
Blade 的 {{ }}
echo 语句会自动通过 PHP 的 htmlspecialchars
函数发送,以防止 XSS 攻击。
您不限于显示传递给视图的变量的内容。您还可以 echo 任何 PHP 函数的结果。实际上,您可以将任何您希望的 PHP 代码放入 Blade echo 语句中
1The current UNIX timestamp is {{ time() }}.
HTML 实体编码
默认情况下,Blade(和 Laravel 的 e
函数)将对 HTML 实体进行双重编码。如果您想禁用双重编码,请从 AppServiceProvider
的 boot
方法中调用 Blade::withoutDoubleEncoding
方法
1<?php 2 3namespace App\Providers; 4 5use Illuminate\Support\Facades\Blade; 6use Illuminate\Support\ServiceProvider; 7 8class AppServiceProvider extends ServiceProvider 9{10 /**11 * Bootstrap any application services.12 */13 public function boot(): void14 {15 Blade::withoutDoubleEncoding();16 }17}
显示未转义的数据
默认情况下,Blade {{ }}
语句会自动通过 PHP 的 htmlspecialchars
函数发送,以防止 XSS 攻击。如果您不希望您的数据被转义,您可以使用以下语法
1Hello, {!! $name !!}.
当 echo 由应用程序用户提供的内容时,请务必小心。在显示用户提供的数据时,您通常应使用转义的双花括号语法来防止 XSS 攻击。
Blade 和 JavaScript 框架
由于许多 JavaScript 框架也使用“花括号”来指示给定的表达式应在浏览器中显示,因此您可以使用 @
符号来通知 Blade 渲染引擎表达式应保持不变。例如
1<h1>Laravel</h1>2 3Hello, @{{ name }}.
在此示例中,@
符号将被 Blade 删除;但是,{{ name }}
表达式将保持 Blade 引擎不变,从而允许 JavaScript 框架对其进行渲染。
@
符号也可用于转义 Blade 指令
1{{-- Blade template --}}2@@if()3 4<!-- HTML output -->5@if()
渲染 JSON
有时,您可能会将数组传递给视图,目的是将其渲染为 JSON,以便初始化 JavaScript 变量。例如
1<script>2 var app = <?php echo json_encode($array); ?>;3</script>
但是,您可以使用 Illuminate\Support\Js::from
方法指令,而不是手动调用 json_encode
。from
方法接受与 PHP 的 json_encode
函数相同的参数;但是,它将确保生成的 JSON 被正确转义,以便包含在 HTML 引号中。from
方法将返回一个字符串 JSON.parse
JavaScript 语句,该语句会将给定的对象或数组转换为有效的 JavaScript 对象
1<script>2 var app = {{ Illuminate\Support\Js::from($array) }};3</script>
最新版本的 Laravel 应用程序骨架包含一个 Js
外观模式,它在您的 Blade 模板中提供了对此功能的便捷访问
1<script>2 var app = {{ Js::from($array) }};3</script>
您应该仅使用 Js::from
方法将现有变量渲染为 JSON。Blade 模板基于正则表达式,尝试将复杂表达式传递给指令可能会导致意外失败。
@verbatim
指令
如果您在模板的很大一部分中显示 JavaScript 变量,则可以将 HTML 包裹在 @verbatim
指令中,这样您就不必在每个 Blade echo 语句前加上 @
符号
1@verbatim2 <div class="container">3 Hello, {{ name }}.4 </div>5@endverbatim
Blade 指令
除了模板继承和显示数据外,Blade 还为常见的 PHP 控制结构(如条件语句和循环)提供了便捷的快捷方式。这些快捷方式提供了一种非常简洁明了的方式来处理 PHP 控制结构,同时对 PHP 同行程序保持熟悉。
If 语句
您可以使用 @if
、@elseif
、@else
和 @endif
指令来构建 if
语句。这些指令的功能与其 PHP 同行程序相同
1@if (count($records) === 1)2 I have one record!3@elseif (count($records) > 1)4 I have multiple records!5@else6 I don't have any records!7@endif
为方便起见,Blade 还提供了 @unless
指令
1@unless (Auth::check())2 You are not signed in.3@endunless
除了已经讨论的条件指令之外,@isset
和 @empty
指令可以用作其各自 PHP 函数的便捷快捷方式
1@isset($records)2 // $records is defined and is not null...3@endisset4 5@empty($records)6 // $records is "empty"...7@endempty
身份验证指令
@auth
和 @guest
指令可用于快速确定当前用户是否已身份验证或是否为访客
1@auth2 // The user is authenticated...3@endauth4 5@guest6 // The user is not authenticated...7@endguest
如果需要,您可以指定在使用 @auth
和 @guest
指令时应检查的身份验证守卫
1@auth('admin')2 // The user is authenticated...3@endauth4 5@guest('admin')6 // The user is not authenticated...7@endguest
环境指令
您可以使用 @production
指令检查应用程序是否在生产环境中运行
1@production2 // Production specific content...3@endproduction
或者,您可以使用 @env
指令确定应用程序是否在特定环境中运行
1@env('staging')2 // The application is running in "staging"...3@endenv4 5@env(['staging', 'production'])6 // The application is running in "staging" or "production"...7@endenv
节指令
您可以使用 @hasSection
指令确定模板继承节是否具有内容
1@hasSection('navigation')2 <div class="pull-right">3 @yield('navigation')4 </div>5 6 <div class="clearfix"></div>7@endif
您可以使用 sectionMissing
指令确定某个节是否没有内容
1@sectionMissing('navigation')2 <div class="pull-right">3 @include('default-navigation')4 </div>5@endif
会话指令
@session
指令可用于确定会话值是否存在。如果会话值存在,则将评估 @session
和 @endsession
指令中的模板内容。在 @session
指令的内容中,您可以 echo $value
变量以显示会话值
1@session('status')2 <div class="p-4 bg-green-100">3 {{ $value }}4 </div>5@endsession
Switch 语句
可以使用 @switch
、@case
、@break
、@default
和 @endswitch
指令来构建 Switch 语句
1@switch($i) 2 @case(1) 3 First case... 4 @break 5 6 @case(2) 7 Second case... 8 @break 9 10 @default11 Default case...12@endswitch
循环
除了条件语句之外,Blade 还提供了用于处理 PHP 循环结构的简单指令。同样,这些指令中的每一个的功能与其 PHP 同行程序相同
1@for ($i = 0; $i < 10; $i++) 2 The current value is {{ $i }} 3@endfor 4 5@foreach ($users as $user) 6 <p>This is user {{ $user->id }}</p> 7@endforeach 8 9@forelse ($users as $user)10 <li>{{ $user->name }}</li>11@empty12 <p>No users</p>13@endforelse14 15@while (true)16 <p>I'm looping forever.</p>17@endwhile
在迭代 foreach
循环时,您可以使用循环变量来获取有关循环的宝贵信息,例如您是否处于循环的第一次或最后一次迭代中。
使用循环时,您还可以使用 @continue
和 @break
指令跳过当前迭代或结束循环
1@foreach ($users as $user) 2 @if ($user->type == 1) 3 @continue 4 @endif 5 6 <li>{{ $user->name }}</li> 7 8 @if ($user->number == 5) 9 @break10 @endif11@endforeach
您还可以在指令声明中包含继续或中断条件
1@foreach ($users as $user)2 @continue($user->type == 1)3 4 <li>{{ $user->name }}</li>5 6 @break($user->number == 5)7@endforeach
循环变量
在迭代 foreach
循环时,$loop
变量将在您的循环内可用。此变量提供对一些有用的信息位的访问,例如当前循环索引以及这是否是循环的第一次或最后一次迭代
1@foreach ($users as $user) 2 @if ($loop->first) 3 This is the first iteration. 4 @endif 5 6 @if ($loop->last) 7 This is the last iteration. 8 @endif 9 10 <p>This is user {{ $user->id }}</p>11@endforeach
如果您处于嵌套循环中,则可以通过 parent
属性访问父循环的 $loop
变量
1@foreach ($users as $user)2 @foreach ($user->posts as $post)3 @if ($loop->parent->first)4 This is the first iteration of the parent loop.5 @endif6 @endforeach7@endforeach
$loop
变量还包含各种其他有用的属性
属性 | 描述 |
---|---|
$loop->index |
当前循环迭代的索引(从 0 开始)。 |
$loop->iteration |
当前循环迭代(从 1 开始)。 |
$loop->remaining |
循环中剩余的迭代次数。 |
$loop->count |
正在迭代的数组中项目的总数。 |
$loop->first |
这是否是循环的第一次迭代。 |
$loop->last |
这是否是循环的最后一次迭代。 |
$loop->even |
这是否是循环的偶数次迭代。 |
$loop->odd |
这是否是循环的奇数次迭代。 |
$loop->depth |
当前循环的嵌套级别。 |
$loop->parent |
在嵌套循环中,父级的循环变量。 |
条件类 & 样式
@class
指令有条件地编译 CSS 类字符串。该指令接受一个类数组,其中数组键包含您希望添加的类,而值是布尔表达式。如果数组元素具有数字键,则它将始终包含在渲染的类列表中
1@php 2 $isActive = false; 3 $hasError = true; 4@endphp 5 6<span @class([ 7 'p-4', 8 'font-bold' => $isActive, 9 'text-gray-500' => ! $isActive,10 'bg-red' => $hasError,11])></span>12 13<span class="p-4 text-gray-500 bg-red"></span>
同样,@style
指令可用于有条件地向 HTML 元素添加内联 CSS 样式
1@php 2 $isActive = true; 3@endphp 4 5<span @style([ 6 'background-color: red', 7 'font-weight: bold' => $isActive, 8])></span> 9 10<span style="background-color: red; font-weight: bold;"></span>
附加属性
为方便起见,您可以使用 @checked
指令轻松指示给定的 HTML 复选框输入是否为“选中”状态。如果提供的条件评估为 true
,则此指令将 echo checked
1<input2 type="checkbox"3 name="active"4 value="active"5 @checked(old('active', $user->active))6/>
同样,@selected
指令可用于指示给定的选择选项是否应为“选中”状态
1<select name="version">2 @foreach ($product->versions as $version)3 <option value="{{ $version }}" @selected(old('version') == $version)>4 {{ $version }}5 </option>6 @endforeach7</select>
此外,@disabled
指令可用于指示给定的元素是否应为“禁用”状态
1<button type="submit" @disabled($errors->isNotEmpty())>Submit</button>
此外,@readonly
指令可用于指示给定的元素是否应为“只读”状态
1<input2 type="email"3 name="email"5 @readonly($user->isNotAdmin())6/>
此外,@required
指令可用于指示给定的元素是否应为“必需”状态
1<input2 type="text"3 name="title"4 value="title"5 @required($user->isAdmin())6/>
包含子视图
虽然您可以自由使用 @include
指令,但 Blade 组件提供了类似的功能,并且与 @include
指令相比,提供了多个优势,例如数据和属性绑定。
Blade 的 @include
指令允许您从另一个视图中包含 Blade 视图。父视图可用的所有变量都将提供给包含的视图
1<div>2 @include('shared.errors')3 4 <form>5 <!-- Form Contents -->6 </form>7</div>
即使包含的视图将继承父视图中可用的所有数据,您也可以传递应提供给包含的视图的附加数据数组
1@include('view.name', ['status' => 'complete'])
如果您尝试 @include
不存在的视图,Laravel 将抛出错误。如果您想包含可能存在也可能不存在的视图,则应使用 @includeIf
指令
1@includeIf('view.name', ['status' => 'complete'])
如果您希望在给定的布尔表达式评估为 true
或 false
时 @include
视图,则可以使用 @includeWhen
和 @includeUnless
指令
1@includeWhen($boolean, 'view.name', ['status' => 'complete'])2 3@includeUnless($boolean, 'view.name', ['status' => 'complete'])
要包含给定视图数组中存在的第一个视图,可以使用 includeFirst
指令
1@includeFirst(['custom.admin', 'admin'], ['status' => 'complete'])
您应避免在 Blade 视图中使用 __DIR__
和 __FILE__
常量,因为它们将引用缓存的、已编译视图的位置。
渲染集合的视图
您可以使用 Blade 的 @each
指令将循环和包含合并为一行
1@each('view.name', $jobs, 'job')
@each
指令的第一个参数是要为数组或集合中的每个元素渲染的视图。第二个参数是要迭代的数组或集合,而第三个参数是将分配给视图中当前迭代的变量名。因此,例如,如果您正在迭代 jobs
数组,通常您希望在视图中将每个作业作为 job
变量访问。当前迭代的数组键将在视图中作为 key
变量可用。
您还可以将第四个参数传递给 @each
指令。此参数确定如果给定数组为空将渲染的视图。
1@each('view.name', $jobs, 'job', 'view.empty')
通过 @each
渲染的视图不继承父视图中的变量。如果子视图需要这些变量,则应改为使用 @foreach
和 @include
指令。
@once
指令
@once
指令允许您定义模板的一部分,该部分在每个渲染周期中仅评估一次。这对于使用堆栈将给定的 JavaScript 代码推送到页面的标头中可能很有用。例如,如果您在循环中渲染给定的组件,您可能希望仅在第一次渲染组件时将 JavaScript 推送到标头
1@once2 @push('scripts')3 <script>4 // Your custom JavaScript...5 </script>6 @endpush7@endonce
由于 @once
指令通常与 @push
或 @prepend
指令结合使用,因此 @pushOnce
和 @prependOnce
指令可供您方便使用
1@pushOnce('scripts')2 <script>3 // Your custom JavaScript...4 </script>5@endPushOnce
原始 PHP
在某些情况下,将 PHP 代码嵌入到视图中很有用。您可以使用 Blade @php
指令在模板中执行纯 PHP 代码块
1@php2 $counter = 1;3@endphp
或者,如果您只需要使用 PHP 导入类,则可以使用 @use
指令
1@use('App\Models\Flight')
可以为 @use
指令提供第二个参数以别名导入的类
1@use('App\Models\Flight', 'FlightModel')
注释
Blade 还允许您在视图中定义注释。但是,与 HTML 注释不同,Blade 注释不包含在应用程序返回的 HTML 中
1{{-- This comment will not be present in the rendered HTML --}}
组件
组件和插槽提供了与节、布局和包含类似的好处;但是,有些人可能会发现组件和插槽的心智模型更容易理解。编写组件有两种方法:基于类的组件和匿名组件。
要创建基于类的组件,您可以使用 make:component
Artisan 命令。为了说明如何使用组件,我们将创建一个简单的 Alert
组件。make:component
命令会将组件放置在 app/View/Components
目录中
1php artisan make:component Alert
make:component
命令还将为组件创建一个视图模板。该视图将放置在 resources/views/components
目录中。当为自己的应用程序编写组件时,组件会在 app/View/Components
目录和 resources/views/components
目录中自动发现,因此通常不需要进一步的组件注册。
您还可以在子目录中创建组件
1php artisan make:component Forms/Input
上面的命令将在 app/View/Components/Forms
目录中创建一个 Input
组件,并且该视图将放置在 resources/views/components/forms
目录中。
如果您想创建匿名组件(仅包含 Blade 模板而没有类的组件),您可以在调用 make:component
命令时使用 --view
标志
1php artisan make:component forms.input --view
上面的命令将在 resources/views/components/forms/input.blade.php
中创建一个 Blade 文件,该文件可以通过 <x-forms.input />
渲染为组件。
手动注册扩展包组件
当为自己的应用程序编写组件时,组件会在 app/View/Components
目录和 resources/views/components
目录中自动发现。
但是,如果您正在构建使用 Blade 组件的扩展包,则需要手动注册组件类及其 HTML 标签别名。您通常应在扩展包的服务提供者的 boot
方法中注册组件
1use Illuminate\Support\Facades\Blade;2 3/**4 * Bootstrap your package's services.5 */6public function boot(): void7{8 Blade::component('package-alert', Alert::class);9}
注册组件后,可以使用其标签别名进行渲染
1<x-package-alert/>
或者,您可以使用 componentNamespace
方法按约定自动加载组件类。例如,Nightshade
扩展包可能具有 Calendar
和 ColorPicker
组件,这些组件位于 Package\Views\Components
命名空间中
1use Illuminate\Support\Facades\Blade;2 3/**4 * Bootstrap your package's services.5 */6public function boot(): void7{8 Blade::componentNamespace('Nightshade\\Views\\Components', 'nightshade');9}
这将允许通过其供应商命名空间使用扩展包组件,使用 package-name::
语法
1<x-nightshade::calendar />2<x-nightshade::color-picker />
Blade 将通过 PascalCase 组件名称自动检测链接到此组件的类。子目录也支持使用“点”表示法。
渲染组件
要显示组件,您可以在 Blade 模板之一中使用 Blade 组件标签。Blade 组件标签以字符串 x-
开头,后跟组件类的 kebab-case 名称
1<x-alert/>2 3<x-user-profile/>
如果组件类嵌套在 app/View/Components
目录的更深层,则可以使用 .
字符来指示目录嵌套。例如,如果我们假设组件位于 app/View/Components/Inputs/Button.php
,我们可以像这样渲染它
1<x-inputs.button/>
如果您想有条件地渲染组件,则可以在组件类上定义 shouldRender
方法。如果 shouldRender
方法返回 false
,则不会渲染组件
1use Illuminate\Support\Str;2 3/**4 * Whether the component should be rendered5 */6public function shouldRender(): bool7{8 return Str::length($this->message) > 0;9}
索引组件
有时,组件是组件组的一部分,您可能希望将相关组件分组在一个目录中。例如,想象一个具有以下类结构的“card”组件
1App\Views\Components\Card\Card2App\Views\Components\Card\Header3App\Views\Components\Card\Body
由于根 Card
组件嵌套在 Card
目录中,因此您可能期望需要通过 <x-card.card>
渲染组件。但是,当组件的文件名与组件目录的名称匹配时,Laravel 会自动假定该组件是“根”组件,并允许您在不重复目录名称的情况下渲染组件
1<x-card>2 <x-card.header>...</x-card.header>3 <x-card.body>...</x-card.body>4</x-card>
向组件传递数据
您可以使用 HTML 属性将数据传递给 Blade 组件。硬编码的原始值可以使用简单的 HTML 属性字符串传递给组件。PHP 表达式和变量应通过使用 :
字符作为前缀的属性传递给组件
1<x-alert type="error" :message="$message"/>
您应在其类构造函数中定义组件的所有数据属性。组件上的所有公共属性将自动提供给组件的视图。无需从组件的 render
方法将数据传递给视图
1<?php 2 3namespace App\View\Components; 4 5use Illuminate\View\Component; 6use Illuminate\View\View; 7 8class Alert extends Component 9{10 /**11 * Create the component instance.12 */13 public function __construct(14 public string $type,15 public string $message,16 ) {}17 18 /**19 * Get the view / contents that represent the component.20 */21 public function render(): View22 {23 return view('components.alert');24 }25}
渲染组件后,您可以通过 echo 变量名称来显示组件的公共变量的内容
1<div class="alert alert-{{ $type }}">2 {{ $message }}3</div>
大小写
组件构造函数参数应使用 camelCase
指定,而在 HTML 属性中引用参数名称时应使用 kebab-case
。例如,给定以下组件构造函数
1/**2 * Create the component instance.3 */4public function __construct(5 public string $alertType,6) {}
可以像这样将 $alertType
参数提供给组件
1<x-alert alert-type="danger" />
短属性语法
在将属性传递给组件时,您还可以使用“短属性”语法。这通常很方便,因为属性名称通常与它们对应的变量名称匹配
1{{-- Short attribute syntax... --}}2<x-profile :$userId :$name />3 4{{-- Is equivalent to... --}}5<x-profile :user-id="$userId" :name="$name" />
转义属性渲染
由于某些 JavaScript 框架(如 Alpine.js)也使用冒号前缀属性,因此您可以使用双冒号 (::
) 前缀来通知 Blade 该属性不是 PHP 表达式。例如,给定以下组件
1<x-button ::class="{ danger: isDeleting }">2 Submit3</x-button>
以下 HTML 将由 Blade 渲染
1<button :class="{ danger: isDeleting }">2 Submit3</button>
组件方法
除了公共变量可用于组件模板外,还可以调用组件上的任何公共方法。例如,想象一个具有 isSelected
方法的组件
1/**2 * Determine if the given option is the currently selected option.3 */4public function isSelected(string $option): bool5{6 return $option === $this->selected;7}
您可以通过调用与方法名称匹配的变量,从组件模板执行此方法
1<option {{ $isSelected($value) ? 'selected' : '' }} value="{{ $value }}">2 {{ $label }}3</option>
在组件类中访问属性和插槽
Blade 组件还允许您在类的 render 方法中访问组件名称、属性和插槽。但是,为了访问此数据,您应该从组件的 render
方法返回一个闭包
1use Closure; 2 3/** 4 * Get the view / contents that represent the component. 5 */ 6public function render(): Closure 7{ 8 return function () { 9 return '<div {{ $attributes }}>Components content</div>';10 };11}
组件的 render
方法返回的闭包也可以接收 $data
数组作为其唯一参数。此数组将包含几个元素,这些元素提供有关组件的信息
1return function (array $data) {2 // $data['componentName'];3 // $data['attributes'];4 // $data['slot'];5 6 return '<div {{ $attributes }}>Components content</div>';7}
$data
数组中的元素绝不应直接嵌入到 render
方法返回的 Blade 字符串中,因为这样做可能会通过恶意属性内容允许远程代码执行。
componentName
等于 HTML 标签中 x-
前缀后使用的名称。因此 <x-alert />
的 componentName
将为 alert
。attributes
元素将包含 HTML 标签上存在的所有属性。slot
元素是一个 Illuminate\Support\HtmlString
实例,其中包含组件插槽的内容。
闭包应返回一个字符串。如果返回的字符串对应于现有视图,则将渲染该视图;否则,返回的字符串将被评估为内联 Blade 视图。
附加依赖项
如果您的组件需要来自 Laravel 的服务容器的依赖项,则可以在任何组件的数据属性之前列出它们,它们将自动由容器注入
1use App\Services\AlertCreator; 2 3/** 4 * Create the component instance. 5 */ 6public function __construct( 7 public AlertCreator $creator, 8 public string $type, 9 public string $message,10) {}
隐藏属性 / 方法
如果您想阻止某些公共方法或属性作为变量暴露给组件模板,则可以将它们添加到组件上的 $except
数组属性中
1<?php 2 3namespace App\View\Components; 4 5use Illuminate\View\Component; 6 7class Alert extends Component 8{ 9 /**10 * The properties / methods that should not be exposed to the component template.11 *12 * @var array13 */14 protected $except = ['type'];15 16 /**17 * Create the component instance.18 */19 public function __construct(20 public string $type,21 ) {}22}
组件属性
我们已经研究了如何将数据属性传递给组件;但是,有时您可能需要指定额外的 HTML 属性(例如 class
),这些属性不是组件运行所需数据的一部分。通常,您希望将这些附加属性传递到组件模板的根元素。例如,假设我们想要像这样渲染 alert
组件
1<x-alert type="error" :message="$message" class="mt-4"/>
所有不属于组件构造函数的属性都将自动添加到组件的“属性包”中。此属性包通过 $attributes
变量自动提供给组件。可以通过 echo 此变量在组件中渲染所有属性
1<div {{ $attributes }}>2 <!-- Component content -->3</div>
目前不支持在组件标签中使用 @env
等指令。例如,<x-alert :live="@env('production')"/>
将不会被编译。
默认 / 合并属性
有时您可能需要为属性指定默认值或将其他值合并到某些组件的属性中。为了实现这一点,您可以使用属性包的 merge
方法。此方法对于定义应始终应用于组件的一组默认 CSS 类特别有用
1<div {{ $attributes->merge(['class' => 'alert alert-'.$type]) }}>2 {{ $message }}3</div>
如果我们假设像这样使用此组件
1<x-alert type="error" :message="$message" class="mb-4"/>
组件的最终渲染 HTML 将如下所示
1<div class="alert alert-error mb-4">2 <!-- Contents of the $message variable -->3</div>
有条件地合并类
有时,如果给定条件为 true
,您可能希望合并类。您可以通过 class
方法完成此操作,该方法接受一个类数组,其中数组键包含您希望添加的类,而值是一个布尔表达式。如果数组元素具有数字键,它将始终包含在呈现的类列表中
1<div {{ $attributes->class(['p-4', 'bg-red' => $hasError]) }}>2 {{ $message }}3</div>
如果您需要将其他属性合并到组件上,您可以将 merge
方法链接到 class
方法
1<button {{ $attributes->class(['p-4'])->merge(['type' => 'button']) }}>2 {{ $slot }}3</button>
如果您需要在不应接收合并属性的其他 HTML 元素上有条件地编译类,则可以使用 @class
指令。
非类属性合并
当合并非 class
属性时,提供给 merge
方法的值将被视为属性的“默认”值。但是,与 class
属性不同,这些属性不会与注入的属性值合并。相反,它们将被覆盖。例如,button
组件的实现可能如下所示
1<button {{ $attributes->merge(['type' => 'button']) }}>2 {{ $slot }}3</button>
要使用自定义 type
渲染按钮组件,可以在使用该组件时指定。如果未指定类型,将使用 button
类型
1<x-button type="submit">2 Submit3</x-button>
此示例中 button
组件的渲染 HTML 将是
1<button type="submit">2 Submit3</button>
如果您希望 class
以外的其他属性将其默认值和注入值连接在一起,则可以使用 prepends
方法。在此示例中,data-controller
属性将始终以 profile-controller
开头,并且任何其他注入的 data-controller
值都将放在此默认值之后
1<div {{ $attributes->merge(['data-controller' => $attributes->prepends('profile-controller')]) }}>2 {{ $slot }}3</div>
检索和筛选属性
您可以使用 filter
方法筛选属性。此方法接受一个闭包,如果您希望将属性保留在属性包中,则应返回 true
1{{ $attributes->filter(fn (string $value, string $key) => $key == 'foo') }}
为方便起见,您可以使用 whereStartsWith
方法检索所有键以给定字符串开头的属性
1{{ $attributes->whereStartsWith('wire:model') }}
相反,可以使用 whereDoesntStartWith
方法排除所有键以给定字符串开头的属性
1{{ $attributes->whereDoesntStartWith('wire:model') }}
使用 first
方法,您可以渲染给定属性包中的第一个属性
1{{ $attributes->whereStartsWith('wire:model')->first() }}
如果您想检查组件上是否存在某个属性,可以使用 has
方法。此方法接受属性名称作为其唯一参数,并返回一个布尔值,指示属性是否存在
1@if ($attributes->has('class'))2 <div>Class attribute is present</div>3@endif
如果将数组传递给 has
方法,该方法将确定组件上是否存在所有给定属性
1@if ($attributes->has(['name', 'class']))2 <div>All of the attributes are present</div>3@endif
可以使用 hasAny
方法确定组件上是否存在任何给定属性
1@if ($attributes->hasAny(['href', ':href', 'v-bind:href']))2 <div>One of the attributes is present</div>3@endif
您可以使用 get
方法检索特定属性的值
1{{ $attributes->get('class') }}
保留关键字
默认情况下,某些关键字为 Blade 内部使用保留,以便渲染组件。以下关键字不能在组件中定义为公共属性或方法名称
data
render
resolveView
shouldRender
view
withAttributes
withName
插槽
您通常需要通过“插槽”将其他内容传递到组件。组件插槽通过回显 $slot
变量来渲染。为了探索这个概念,让我们想象一下 alert
组件具有以下标记
1<!-- /resources/views/components/alert.blade.php -->2 3<div class="alert alert-danger">4 {{ $slot }}5</div>
我们可以通过将内容注入到组件中来将内容传递到 slot
1<x-alert>2 <strong>Whoops!</strong> Something went wrong!3</x-alert>
有时,组件可能需要在组件内的不同位置渲染多个不同的插槽。让我们修改我们的警报组件,以允许注入“title”插槽
1<!-- /resources/views/components/alert.blade.php -->2 3<span class="alert-title">{{ $title }}</span>4 5<div class="alert alert-danger">6 {{ $slot }}7</div>
您可以使用 x-slot
标签定义命名插槽的内容。任何不在显式 x-slot
标签内的内容都将通过 $slot
变量传递到组件
1<x-alert>2 <x-slot:title>3 Server Error4 </x-slot>5 6 <strong>Whoops!</strong> Something went wrong!7</x-alert>
您可以调用插槽的 isEmpty
方法来确定插槽是否包含内容
1<span class="alert-title">{{ $title }}</span>2 3<div class="alert alert-danger">4 @if ($slot->isEmpty())5 This is default content if the slot is empty.6 @else7 {{ $slot }}8 @endif9</div>
此外,hasActualContent
方法可用于确定插槽是否包含任何不是 HTML 注释的“实际”内容
1@if ($slot->hasActualContent())2 The scope has non-comment content.3@endif
作用域插槽
如果您使用过 Vue 等 JavaScript 框架,您可能熟悉“作用域插槽”,它允许您从插槽内的组件访问数据或方法。您可以通过在组件上定义公共方法或属性,并通过 $component
变量在插槽内访问组件,从而在 Laravel 中实现类似的行为。在此示例中,我们将假设 x-alert
组件在其组件类上定义了一个公共 formatAlert
方法
1<x-alert>2 <x-slot:title>3 {{ $component->formatAlert('Server Error') }}4 </x-slot>5 6 <strong>Whoops!</strong> Something went wrong!7</x-alert>
插槽属性
与 Blade 组件一样,您可以为插槽分配额外的 属性,例如 CSS 类名
1<x-card class="shadow-sm"> 2 <x-slot:heading class="font-bold"> 3 Heading 4 </x-slot> 5 6 Content 7 8 <x-slot:footer class="text-sm"> 9 Footer10 </x-slot>11</x-card>
要与插槽属性交互,您可以访问插槽变量的 attributes
属性。有关如何与属性交互的更多信息,请查阅有关 组件属性 的文档
1@props([ 2 'heading', 3 'footer', 4]) 5 6<div {{ $attributes->class(['border']) }}> 7 <h1 {{ $heading->attributes->class(['text-lg']) }}> 8 {{ $heading }} 9 </h1>10 11 {{ $slot }}12 13 <footer {{ $footer->attributes->class(['text-gray-700']) }}>14 {{ $footer }}15 </footer>16</div>
内联组件视图
对于非常小的组件,同时管理组件类和组件的视图模板可能会感到繁琐。因此,您可以直接从 render
方法返回组件的标记
1/** 2 * Get the view / contents that represent the component. 3 */ 4public function render(): string 5{ 6 return <<<'blade' 7 <div class="alert alert-danger"> 8 {{ $slot }} 9 </div>10 blade;11}
生成内联视图组件
要创建渲染内联视图的组件,您可以在执行 make:component
命令时使用 inline
选项
1php artisan make:component Alert --inline
动态组件
有时您可能需要渲染一个组件,但直到运行时才知道应该渲染哪个组件。在这种情况下,您可以使用 Laravel 内置的 dynamic-component
组件根据运行时值或变量渲染组件
1// $componentName = "secondary-button";2 3<x-dynamic-component :component="$componentName" class="mt-4" />
手动注册组件
以下关于手动注册组件的文档主要适用于编写包含视图组件的 Laravel 软件包的开发者。如果您不是在编写软件包,则组件文档的这一部分可能与您无关。
当为自己的应用程序编写组件时,组件会在 app/View/Components
目录和 resources/views/components
目录中自动发现。
但是,如果您正在构建一个使用 Blade 组件的软件包,或将组件放置在非常规目录中,您将需要手动注册您的组件类及其 HTML 标签别名,以便 Laravel 知道在哪里找到该组件。您通常应该在软件包服务提供程序的 boot
方法中注册您的组件
1use Illuminate\Support\Facades\Blade; 2use VendorPackage\View\Components\AlertComponent; 3 4/** 5 * Bootstrap your package's services. 6 */ 7public function boot(): void 8{ 9 Blade::component('package-alert', AlertComponent::class);10}
注册组件后,可以使用其标签别名进行渲染
1<x-package-alert/>
自动加载软件包组件
或者,您可以使用 componentNamespace
方法按约定自动加载组件类。例如,Nightshade
扩展包可能具有 Calendar
和 ColorPicker
组件,这些组件位于 Package\Views\Components
命名空间中
1use Illuminate\Support\Facades\Blade;2 3/**4 * Bootstrap your package's services.5 */6public function boot(): void7{8 Blade::componentNamespace('Nightshade\\Views\\Components', 'nightshade');9}
这将允许通过其供应商命名空间使用扩展包组件,使用 package-name::
语法
1<x-nightshade::calendar />2<x-nightshade::color-picker />
Blade 将通过 PascalCase 组件名称自动检测链接到此组件的类。子目录也支持使用“点”表示法。
匿名组件
与内联组件类似,匿名组件提供了一种通过单个文件管理组件的机制。但是,匿名组件使用单个视图文件,并且没有关联的类。要定义匿名组件,您只需要将 Blade 模板放置在 resources/views/components
目录中即可。例如,假设您在 resources/views/components/alert.blade.php
中定义了一个组件,您可以像这样简单地渲染它
1<x-alert/>
您可以使用 .
字符来指示组件是否嵌套在 components
目录的更深处。例如,假设组件在 resources/views/components/inputs/button.blade.php
中定义,您可以像这样渲染它
1<x-inputs.button/>
匿名索引组件
有时,当组件由许多 Blade 模板组成时,您可能希望将给定组件的模板分组在一个目录中。例如,想象一个具有以下目录结构的“手风琴”组件
1/resources/views/components/accordion.blade.php2/resources/views/components/accordion/item.blade.php
此目录结构允许您像这样渲染手风琴组件及其项目
1<x-accordion>2 <x-accordion.item>3 ...4 </x-accordion.item>5</x-accordion>
但是,为了通过 x-accordion
渲染手风琴组件,我们被迫将 “index” 手风琴组件模板放置在 resources/views/components
目录中,而不是将其与其他手风琴相关模板一起嵌套在 accordion
目录中。
值得庆幸的是,Blade 允许您在组件目录本身中放置与组件目录名称匹配的文件。当此模板存在时,即使它嵌套在目录中,也可以将其渲染为组件的“根”元素。因此,我们可以继续使用上面示例中给出的相同 Blade 语法;但是,我们将调整我们的目录结构,如下所示
1/resources/views/components/accordion/accordion.blade.php2/resources/views/components/accordion/item.blade.php
数据属性
由于匿名组件没有任何关联的类,您可能想知道如何区分哪些数据应该作为变量传递给组件,哪些属性应该放置在组件的 属性包 中。
您可以使用组件 Blade 模板顶部的 @props
指令指定哪些属性应被视为数据变量。组件上的所有其他属性都将通过组件的属性包提供。如果您希望为数据变量提供默认值,则可以将变量的名称指定为数组键,将默认值指定为数组值
1<!-- /resources/views/components/alert.blade.php -->2 3@props(['type' => 'info', 'message'])4 5<div {{ $attributes->merge(['class' => 'alert alert-'.$type]) }}>6 {{ $message }}7</div>
给定上面的组件定义,我们可以像这样渲染组件
1<x-alert type="error" :message="$message" class="mb-4"/>
访问父级数据
有时您可能希望从子组件内部访问父组件的数据。在这些情况下,您可以使用 @aware
指令。例如,想象一下我们正在构建一个复杂的菜单组件,该组件由父 <x-menu>
和子 <x-menu.item>
组成
1<x-menu color="purple">2 <x-menu.item>...</x-menu.item>3 <x-menu.item>...</x-menu.item>4</x-menu>
<x-menu>
组件的实现可能如下所示
1<!-- /resources/views/components/menu/index.blade.php -->2 3@props(['color' => 'gray'])4 5<ul {{ $attributes->merge(['class' => 'bg-'.$color.'-200']) }}>6 {{ $slot }}7</ul>
由于 color
prop 仅传递到父组件 (<x-menu>
),因此它在 <x-menu.item>
中不可用。但是,如果我们使用 @aware
指令,我们可以使其在 <x-menu.item>
中也可用
1<!-- /resources/views/components/menu/item.blade.php -->2 3@aware(['color' => 'gray'])4 5<li {{ $attributes->merge(['class' => 'text-'.$color.'-800']) }}>6 {{ $slot }}7</li>
@aware
指令无法访问未通过 HTML 属性显式传递到父组件的父数据。未显式传递到父组件的默认 @props
值无法被 @aware
指令访问。
匿名组件路径
如前所述,匿名组件通常通过将 Blade 模板放置在 resources/views/components
目录中来定义。但是,您有时可能希望向 Laravel 注册除默认路径之外的其他匿名组件路径。
anonymousComponentPath
方法接受匿名组件位置的 “路径” 作为其第一个参数,以及组件应放置在其下的可选 “命名空间” 作为其第二个参数。通常,此方法应从应用程序的 服务提供程序 之一的 boot
方法中调用
1/**2 * Bootstrap any application services.3 */4public function boot(): void5{6 Blade::anonymousComponentPath(__DIR__.'/../components');7}
当组件路径在没有指定前缀的情况下注册时,如上面的示例所示,它们也可以在您的 Blade 组件中渲染,而无需相应的前缀。例如,如果 panel.blade.php
组件存在于上面注册的路径中,则可以像这样渲染它
1<x-panel />
前缀 “命名空间” 可以作为第二个参数提供给 anonymousComponentPath
方法
1Blade::anonymousComponentPath(__DIR__.'/../components', 'dashboard');
当提供前缀时,可以通过在渲染组件时将组件的命名空间前缀到组件名称来渲染该 “命名空间” 中的组件
1<x-dashboard::panel />
构建布局
使用组件进行布局
大多数 Web 应用程序在各个页面上保持相同的通用布局。如果我们需要在我们创建的每个视图中重复整个布局 HTML,那将是非常繁琐且难以维护我们的应用程序。值得庆幸的是,将此布局定义为单个 Blade 组件,然后在整个应用程序中使用它非常方便。
定义布局组件
例如,假设我们正在构建一个 “待办事项” 列表应用程序。我们可以定义一个 layout
组件,如下所示
1<!-- resources/views/components/layout.blade.php --> 2 3<html> 4 <head> 5 <title>{{ $title ?? 'Todo Manager' }}</title> 6 </head> 7 <body> 8 <h1>Todos</h1> 9 <hr/>10 {{ $slot }}11 </body>12</html>
应用布局组件
定义 layout
组件后,我们可以创建一个使用该组件的 Blade 视图。在此示例中,我们将定义一个显示任务列表的简单视图
1<!-- resources/views/tasks.blade.php -->2 3<x-layout>4 @foreach ($tasks as $task)5 <div>{{ $task }}</div>6 @endforeach7</x-layout>
请记住,注入到组件中的内容将提供给 layout
组件内的默认 $slot
变量。您可能已经注意到,我们的 layout
还尊重 $title
插槽(如果提供),否则将显示默认标题。我们可以使用 组件文档 中讨论的标准插槽语法从我们的任务列表视图中注入自定义标题
1<!-- resources/views/tasks.blade.php --> 2 3<x-layout> 4 <x-slot:title> 5 Custom Title 6 </x-slot> 7 8 @foreach ($tasks as $task) 9 <div>{{ $task }}</div>10 @endforeach11</x-layout>
现在我们已经定义了我们的布局和任务列表视图,我们只需要从路由返回 task
视图
1use App\Models\Task;2 3Route::get('/tasks', function () {4 return view('tasks', ['tasks' => Task::all()]);5});
使用模板继承进行布局
定义布局
布局也可以通过 “模板继承” 创建。这是在引入 组件 之前构建应用程序的主要方式。
首先,让我们看一个简单的例子。首先,我们将检查页面布局。由于大多数 Web 应用程序在各个页面上保持相同的通用布局,因此将此布局定义为单个 Blade 视图非常方便
1<!-- resources/views/layouts/app.blade.php --> 2 3<html> 4 <head> 5 <title>App Name - @yield('title')</title> 6 </head> 7 <body> 8 @section('sidebar') 9 This is the master sidebar.10 @show11 12 <div class="container">13 @yield('content')14 </div>15 </body>16</html>
如您所见,此文件包含典型的 HTML 标记。但是,请注意 @section
和 @yield
指令。顾名思义,@section
指令定义内容的一部分,而 @yield
指令用于显示给定部分的内容。
现在我们已经为我们的应用程序定义了一个布局,让我们定义一个继承该布局的子页面。
扩展布局
在定义子视图时,使用 @extends
Blade 指令来指定子视图应 “继承” 的布局。扩展 Blade 布局的视图可以使用 @section
指令将内容注入到布局的部分中。请记住,如上面的示例所示,这些部分的内容将使用 @yield
显示在布局中
1<!-- resources/views/child.blade.php --> 2 3@extends('layouts.app') 4 5@section('title', 'Page Title') 6 7@section('sidebar') 8 @@parent 9 10 <p>This is appended to the master sidebar.</p>11@endsection12 13@section('content')14 <p>This is my body content.</p>15@endsection
在此示例中,sidebar
部分使用 @@parent
指令将内容附加(而不是覆盖)到布局的侧边栏。当视图呈现时,@@parent
指令将被布局的内容替换。
与之前的示例相反,此 sidebar
部分以 @endsection
而不是 @show
结尾。@endsection
指令只会定义一个部分,而 @show
将定义并立即产生该部分。
@yield
指令还接受默认值作为其第二个参数。如果未定义要产生的节,则将呈现此值
1@yield('content', 'Default content')
表单
CSRF 字段
每当您在应用程序中定义 HTML 表单时,都应在表单中包含一个隐藏的 CSRF 令牌字段,以便 CSRF 保护 中间件可以验证请求。您可以使用 @csrf
Blade 指令来生成令牌字段
1<form method="POST" action="/profile">2 @csrf3 4 ...5</form>
方法字段
由于 HTML 表单无法发出 PUT
、PATCH
或 DELETE
请求,因此您需要添加一个隐藏的 _method
字段来模拟这些 HTTP 动词。@method
Blade 指令可以为您创建此字段
1<form action="/foo/bar" method="POST">2 @method('PUT')3 4 ...5</form>
验证错误
@error
指令可用于快速检查给定属性是否存在 验证错误消息。在 @error
指令中,您可以回显 $message
变量以显示错误消息
1<!-- /resources/views/post/create.blade.php --> 2 3<label for="title">Post Title</label> 4 5<input 6 id="title" 7 type="text" 8 class="@error('title') is-invalid @enderror" 9/>10 11@error('title')12 <div class="alert alert-danger">{{ $message }}</div>13@enderror
由于 @error
指令会编译为 “if” 语句,因此您可以使用 @else
指令在属性没有错误时呈现内容
1<!-- /resources/views/auth.blade.php -->2 3<label for="email">Email address</label>4 5<input6 id="email"7 type="email"8 class="@error('email') is-invalid @else is-valid @enderror"9/>
您可以将 特定错误包的名称 作为第二个参数传递给 @error
指令,以检索包含多个表单的页面上的验证错误消息
1<!-- /resources/views/auth.blade.php --> 2 3<label for="email">Email address</label> 4 5<input 6 id="email" 7 type="email" 8 class="@error('email', 'login') is-invalid @enderror" 9/>10 11@error('email', 'login')12 <div class="alert alert-danger">{{ $message }}</div>13@enderror
堆栈
Blade 允许您推送到命名堆栈,这些堆栈可以在另一个视图或布局中的其他位置呈现。这对于指定子视图所需的任何 JavaScript 库特别有用
1@push('scripts')2 <script src="/example.js"></script>3@endpush
如果您想在给定的布尔表达式评估为 true
时 @push
内容,您可以使用 @pushIf
指令
1@pushIf($shouldPush, 'scripts')2 <script src="/example.js"></script>3@endPushIf
您可以根据需要多次推送到堆栈。要渲染完整的堆栈内容,请将堆栈的名称传递给 @stack
指令
1<head>2 <!-- Head Contents -->3 4 @stack('scripts')5</head>
如果您想将内容前置到堆栈的开头,则应使用 @prepend
指令
1@push('scripts')2 This will be second...3@endpush4 5// Later...6 7@prepend('scripts')8 This will be first...9@endprepend
服务注入
@inject
指令可用于从 Laravel 服务容器 中检索服务。传递给 @inject
的第一个参数是将放置服务的变量的名称,而第二个参数是您希望解析的服务的类或接口名称
1@inject('metrics', 'App\Services\MetricsService')2 3<div>4 Monthly Revenue: {{ $metrics->monthlyRevenue() }}.5</div>
渲染内联 Blade 模板
有时您可能需要将原始 Blade 模板字符串转换为有效的 HTML。您可以使用 Blade
facade 提供的 render
方法来完成此操作。render
方法接受 Blade 模板字符串和一个可选的数据数组,以提供给模板
1use Illuminate\Support\Facades\Blade;2 3return Blade::render('Hello, {{ $name }}', ['name' => 'Julian Bashir']);
Laravel 通过将内联 Blade 模板写入 storage/framework/views
目录来渲染它们。如果您希望 Laravel 在渲染 Blade 模板后删除这些临时文件,您可以向该方法提供 deleteCachedView
参数
1return Blade::render(2 'Hello, {{ $name }}',3 ['name' => 'Julian Bashir'],4 deleteCachedView: true5);
渲染 Blade 片段
当使用前端框架(如 Turbo 和 htmx)时,您有时可能只需要在 HTTP 响应中返回 Blade 模板的一部分。Blade “片段” 允许您做到这一点。首先,将 Blade 模板的一部分放置在 @fragment
和 @endfragment
指令中
1@fragment('user-list')2 <ul>3 @foreach ($users as $user)4 <li>{{ $user->name }}</li>5 @endforeach6 </ul>7@endfragment
然后,当渲染使用此模板的视图时,您可以调用 fragment
方法来指定只有指定的片段应包含在传出的 HTTP 响应中
1return view('dashboard', ['users' => $users])->fragment('user-list');
fragmentIf
方法允许您根据给定条件有条件地返回视图的片段。否则,将返回整个视图
1return view('dashboard', ['users' => $users])2 ->fragmentIf($request->hasHeader('HX-Request'), 'user-list');
fragments
和 fragmentsIf
方法允许您在响应中返回多个视图片段。这些片段将连接在一起
1view('dashboard', ['users' => $users])2 ->fragments(['user-list', 'comment-list']);3 4view('dashboard', ['users' => $users])5 ->fragmentsIf(6 $request->hasHeader('HX-Request'),7 ['user-list', 'comment-list']8 );
扩展 Blade
Blade 允许您使用 directive
方法定义自己的自定义指令。当 Blade 编译器遇到自定义指令时,它将使用指令包含的表达式调用提供的回调。
以下示例创建了一个 @datetime($var)
指令,该指令格式化给定的 $var
,它应该是 DateTime
的实例
1<?php 2 3namespace App\Providers; 4 5use Illuminate\Support\Facades\Blade; 6use Illuminate\Support\ServiceProvider; 7 8class AppServiceProvider extends ServiceProvider 9{10 /**11 * Register any application services.12 */13 public function register(): void14 {15 // ...16 }17 18 /**19 * Bootstrap any application services.20 */21 public function boot(): void22 {23 Blade::directive('datetime', function (string $expression) {24 return "<?php echo ($expression)->format('m/d/Y H:i'); ?>";25 });26 }27}
如您所见,我们将 format
方法链接到传递给指令的任何表达式。因此,在此示例中,此指令生成的最终 PHP 将是
1<?php echo ($var)->format('m/d/Y H:i'); ?>
在更新 Blade 指令的逻辑后,您需要删除所有缓存的 Blade 视图。可以使用 view:clear
Artisan 命令删除缓存的 Blade 视图。
自定义 Echo 处理程序
如果您尝试使用 Blade “echo” 对象,则将调用该对象的 __toString
方法。__toString
方法是 PHP 内置的 “魔术方法” 之一。但是,有时您可能无法控制给定类的 __toString
方法,例如当您正在交互的类属于第三方库时。
在这些情况下,Blade 允许您为该特定类型的对象注册自定义 echo 处理程序。为此,您应该调用 Blade 的 stringable
方法。stringable
方法接受一个闭包。此闭包应类型提示它负责渲染的对象类型。通常,stringable
方法应在应用程序的 AppServiceProvider
类的 boot
方法中调用
1use Illuminate\Support\Facades\Blade; 2use Money\Money; 3 4/** 5 * Bootstrap any application services. 6 */ 7public function boot(): void 8{ 9 Blade::stringable(function (Money $money) {10 return $money->formatTo('en_GB');11 });12}
定义自定义 echo 处理程序后,您可以简单地在 Blade 模板中回显该对象
1Cost: {{ $money }}
自定义 If 语句
当定义简单的自定义条件语句时,编程自定义指令有时比必要的更复杂。因此,Blade 提供了 Blade::if
方法,该方法允许您使用闭包快速定义自定义条件指令。例如,让我们定义一个自定义条件,该条件检查应用程序配置的默认 “磁盘”。我们可以在 AppServiceProvider
的 boot
方法中执行此操作
1use Illuminate\Support\Facades\Blade; 2 3/** 4 * Bootstrap any application services. 5 */ 6public function boot(): void 7{ 8 Blade::if('disk', function (string $value) { 9 return config('filesystems.default') === $value;10 });11}
定义自定义条件后,您可以在模板中使用它
1@disk('local') 2 <!-- The application is using the local disk... --> 3@elsedisk('s3') 4 <!-- The application is using the s3 disk... --> 5@else 6 <!-- The application is using some other disk... --> 7@enddisk 8 9@unlessdisk('local')10 <!-- The application is not using the local disk... -->11@enddisk