Blade 模板
介绍
Blade 是 Laravel 提供的简单而强大的模板引擎。与其他流行的 PHP 模板引擎不同,Blade 不限制您在视图中使用纯 PHP 代码。所有 Blade 视图都被编译成纯 PHP 代码并缓存,直到它们被修改,这意味着 Blade 对您的应用程序几乎没有额外的开销。Blade 视图文件使用 .blade.php
文件扩展名,通常存储在 resources/views
目录中。
模板继承
定义布局
使用 Blade 的两个主要好处是 模板继承 和 部分。首先,让我们来看一个简单的例子。首先,我们将检查一个“主”页面布局。由于大多数 Web 应用程序在各个页面之间保持相同的总体布局,因此将此布局定义为单个 Blade 视图是很方便的:
<!-- 存储在 resources/views/layouts/master.blade.php -->
<html>
<head>
<title>应用名称 - @yield('title')</title>
</head>
<body>
@section('sidebar')
这是主侧边栏。
@show
<div class="container">
@yield('content')
</div>
</body>
</html>
如您所见,此文件包含典型的 HTML 标记。但是,请注意 @section
和 @yield
指令。顾名思义,@section
指令定义了一部分内容,而 @yield
指令用于显示给定部分的内容。
现在我们已经为我们的应用程序定义了一个布局,让我们定义一个继承该布局的子页面。
扩展布局
在定义子页面时,您可以使用 Blade 的 @extends
指令来指定子页面应“继承”哪个布局。使用 @extends
Blade 布局的视图可以使用 @section
指令将内容注入布局的部分。请记住,如上例所示,这些部分的内容将使用 @yield
在布局中显示:
<!-- 存储在 resources/views/child.blade.php -->
@extends('layouts.master')
@section('title', '页面标题')
@section('sidebar')
@@parent
<p>这是附加到主侧边栏的内容。</p>
@endsection
@section('content')
<p>这是我的正文内容。</p>
@endsection
在此示例中,sidebar
部分使用 @@parent
指令将内容附加(而不是覆盖)到布局的侧边栏。@@parent
指令将在视图呈现时被布局的内容替换。
当然,就像普通的 PHP 视图一样,Blade 视图可以使用全局 view
辅助函数从路由返回:
Route::get('blade', function () {
return view('child');
});
显示数据
您可以通过将变量包裹在“花括号”中来显示传递给 Blade 视图的数据。例如,给定以下路由:
Route::get('greeting', function () {
return view('welcome', ['name' => 'Samantha']);
});
您可以像这样显示 name
变量的内容:
Hello, {{ $name }}.
当然,您不仅限于显示传递给视图的变量的内容。您还可以回显任何 PHP 函数的结果。实际上,您可以在 Blade 回显语句中放置任何您希望的 PHP 代码:
当前的 UNIX 时间戳是 {{ time() }}.
Blade {{ }}
语句会自动通过 PHP 的 htmlentities
函数以防止 XSS 攻击。
Blade 与 JavaScript 框架
由于许多 JavaScript 框架也使用“花括号”来表示应在浏览器中显示的表达式,您可以使用 @
符号来通知 Blade 渲染引擎表达式应保持不变。例如:
<h1>Laravel</h1>
Hello, @{{ name }}.
在此示例中,@
符号将被 Blade 移除;然而,{{ name }}
表达式将保持不变,由您的 JavaScript 框架渲染。
如果存在则回显数据
有时您可能希望回显一个变量,但不确定该变量是否已设置。我们可以用详细的 PHP 代码来表达这一点:
{{ isset($name) ? $name : '默认' }}
然而,Blade 提供了以下方便的快捷方式,而不是编写三元语句:
{{ $name or '默认' }}
在此示例中,如果 $name
变量存在,则会显示其值。然而,如果它不存在,则会显示“默认”一词。
显示未转义的数据
默认情况下,Blade {{ }}
语句会自动通过 PHP 的 htmlentities
函数以防止 XSS 攻击。如果您不希望数据被转义,可以使用以下语法:
Hello, {!! $name !!}.
在回显由应用程序用户提供的内容时要非常小心。始终使用双花括号语法来转义内容中的任何 HTML 实体。
控制结构
除了模板继承和显示数据,Blade 还为常见的 PHP 控制结构(如条件语句和循环)提供了方便的快捷方式。这些快捷方式提供了一种非常简洁的方式来处理 PHP 控制结构,同时也保持了与 PHP 对应结构的熟悉性。
If 语句
您可以使用 @if
、@elseif
、@else
和 @endif
指令构建 if
语句。这些指令的功能与其 PHP 对应结构完全相同:
@if (count($records) === 1)
我有一条记录!
@elseif (count($records) > 1)
我有多条记录!
@else
我没有任何记录!
@endif
为了方便起见,Blade 还提供了一个 @unless
指令:
@unless (Auth::check())
您尚未登录。
@endunless
您还可以使用 @hasSection
指令来确定给定的布局部分是否有任何内容:
<title>
@hasSection ('title')
@yield('title') - 应用名称
@else
应用名称
@endif
</title>
循环
除了条件语句,Blade 还提供了用于处理 PHP 支持的循环结构的简单指令。同样,这些指令的功能与其 PHP 对应结构完全相同:
@for ($i = 0; $i < 10; $i++)
当前值是 {{ $i }}
@endfor
@foreach ($users as $user)
<p>这是用户 {{ $user->id }}</p>
@endforeach
@forelse ($users as $user)
<li>{{ $user->name }}</li>
@empty
<p>没有用户</p>
@endforelse
@while (true)
<p>我在无限循环。</p>
@endwhile
在使用循环时,您可能需要结束循环或跳过当前迭代:
@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
包含子视图
Blade 的 @include
指令允许您轻松地从现有视图中包含一个 Blade 视图。所有可用于父视图的变量都将可用于包含的视图:
<div>
@include('shared.errors')
<form>
<!-- 表单内容 -->
</form>
</div>
即使包含的视图将继承父视图中可用的所有数据,您也可以将额外数据数组传递给包含的视图:
@include('view.name', ['some' => 'data'])
您应该避免在 Blade 视图中使用 __DIR__
和 __FILE__
常量,因为它们将引用缓存视图的位置。
为集合渲染视图
您可以将循环和包含结合到一行中,使用 Blade 的 @each
指令:
@each('view.name', $jobs, 'job')
第一个参数是要为数组或集合中的每个元素渲染的视图部分。第二个参数是您希望迭代的数组或集合,而第三个参数是将在视图中分配给当前迭代的变量名。因此,例如,如果您正在迭代 jobs
数组,通常您希望在视图部分中将每个作业作为 job
变量访问。当前迭代的键将在视图部分中作为 key
变量可用。
您还可以将第四个参数传递给 @each
指令。此参数确定如果给定数组为空,将渲染哪个视图。
@each('view.name', $jobs, 'job', 'view.empty')
注释
Blade 还允许您在视图中定义注释。然而,与 HTML 注释不同,Blade 注释不会包含在应用程序返回的 HTML 中:
{{-- 此注释不会出现在渲染的 HTML 中 --}}
堆栈
Blade 还允许您推送到命名堆栈,这些堆栈可以在另一个视图或布局中渲染:
@push('scripts')
<script src="/example.js"></script>
@endpush
您可以根据需要多次推送到同一个堆栈。要渲染堆栈,请使用 @stack
语法:
<head>
<!-- 头部内容 -->
@stack('scripts')
</head>
服务注入
@inject
指令可用于从 Laravel 服务容器 中检索服务。传递给 @inject
的第一个参数是服务将放入的变量的名称,而第二个参数是您希望解析的服务的类/接口名称:
@inject('metrics', 'App\Services\MetricsService')
<div>
月收入:{{ $metrics->monthlyRevenue() }}。
</div>
扩展 Blade
Blade 甚至允许您定义自己的自定义指令。您可以使用 directive
方法注册指令。当 Blade 编译器遇到指令时,它会调用提供的回调及其参数。
以下示例创建了一个 @datetime($var)
指令,用于格式化给定的 $var
:
<?php
namespace App\Providers;
use Blade;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* 执行服务的注册后引导。
*
* @return void
*/
public function boot()
{
Blade::directive('datetime', function($expression) {
return "<?php echo with{$expression}->format('m/d/Y H:i'); ?>";
});
}
/**
* 在容器中注册绑定。
*
* @return void
*/
public function register()
{
//
}
}
如您所见,此指令中使用了 Laravel 的 with
辅助函数。with
辅助函数只是返回它所给的对象/值,允许方便的方法链。此指令生成的最终 PHP 将是:
<?php echo with($var)->format('m/d/Y H:i'); ?>
在更新 Blade 指令的逻辑后,您需要删除所有缓存的 Blade 视图。可以使用 view:clear
Artisan 命令删除缓存的 Blade 视图。