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