Laravel Blade 模板
简介
Blade是Laravel提供的简单但功能强大的模板引擎。与其他流行的PHP模板引擎不同,Blade不会限制我们在视图中使用纯PHP代码。实际上,所有Blade视图都被编译为纯PHP代码并被缓存起来。blade视图文件使用.blade.php
文件扩展名,并且通常存储在resources/views
目录中。
模板继承
定义布局
使用Blade的两个主要好处是模板继承和section。首先,让我们看一个简单的例子。我们将检查“主”页面的布局。由于大多数Web应用程序在各个页面上都保持相同的总体布局,因此将这种布局定义为单个Blade视图很方便:
<!-- Stored in 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 伪指令用于显示给定部分的内容。
现在,我们已经为应用程序定义了一个布局,让我们定义一个继承该布局的子页面。
扩展布局
定义子视图时,请使用Blade @extends
指令指定子视图应“继承”的布局。扩展Blade布局的视图可以使用@section
指令将内容注入到布局的各节中。请记住,如上例所示,这些部分的内容将在布局中使用@yield引用显示:
<!-- Stored in 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呈现视图时,该指令将被布局的内容替换,也就是说@parent
相当于一个占位符。
与前面的示例相反,sidebar部分以
@endsection
结束,而不是使用@show。@endsection指令将只定义一个内容块,而@show不仅仅是定义内容块,而是在定义之后立即引用该部分。
@yield
指令还有第二个参数,这个参数指定一个默认值。如果产生的部分未定义,则将呈现此值:
@yield('content', View::make('view.name'))
blade 视图可以使用全局view帮助函数从路由中直接返回:
Route::get('blade', function () {
return view('child');
});
显示数据
我们可以通过在变量外面加上花括号,使得该变量可以在视图中显示。例如,给定以下路由:
Route::get('greeting', function () {
return view('welcome', ['name' => 'Samantha']);
});
我们可以这样显示name变量的内容:
Hello, {{ $name }}.
Blade
{{ }}
语句通过PHP的htmlspecialchars
功能自动发送,以防止XSS攻击。
不仅限于显示传递给视图的变量的内容。也可以在视图中调用任何的PHP函数,并显示函数的返回值。实际上,可以将所需的任何PHP代码放入Blade echo语句中:
The current UNIX timestamp is {{ time() }}.
显示未转义的数据
默认情况下,Blade {{ }}
语句通过PHP的htmlspecialchars功能自动发送,以防止XSS攻击。如果您不希望对数据进行转义,则可以使用以下语法:
Hello, {!! $name !!}.
显示用户提供的内容时,要格外小心。在显示用户提供的数据时,建议始终使用转义的双花括号语法来防止XSS攻击。
渲染JSON
有时,可能会将数组传递给视图。然后将其呈现为JSON,以便初始化JavaScript变量。例如:
<script>
var app = <?php echo json_encode($array); ?>;
</script>
可以使用@json
指令代替json_encode
。@json指令接受与PHP json_encode
函数相同的参数:
<script>
var app = @json($array);
var app = @json($array, JSON_PRETTY_PRINT);
</script>
我们应该使用@json指令将现有变量呈现为JSON。Blade模板基于正则表达式,尝试将复杂的表达式传递给指令可能会导致意外失败。
HTML实体编码
默认情况下,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.
*
* @return void
*/
public function boot()
{
Blade::withoutDoubleEncoding();
}
}
Blade 和 JavaScript 框架
由于许多JavaScript框架还使用“大括号”来指示应在浏览器中显示给定的表达式,因此可以使用@
符号来通知Blade渲染引擎其后面的表达式应保持不变。例如:
<h1>Laravel</h1>
Hello, @{{ name }}.
在此示例中,@符号将被Blade删除;但是,{{ name }}Blade引擎不会去处理,这样就可以使JavaScript框架来处理了。
@
符号还可用于转义Blade指令:
{{-- Blade --}}
@@json()
<!-- HTML output -->
@json()
@verbatim 指令
如果要在模板的很大一部分中显示JavaScript变量,则可以将HTML包装在@verbatim
指令中,这样就不必在每个Blade echo语句前添加@符号前缀:
@verbatim
<div class="container">
Hello, {{ name }}.
</div>
@endverbatim
控制结构
除了模板继承和显示数据,Blade还为常见的PHP控制结构(如条件语句和循环)提供了快捷方式。这些快捷方式为使用PHP控制结构提供了一种非常简洁的简洁方法。
if 语句
我们在构建if
语句时可以使用@if
,@elseif
,@else
和@endif
指令。这些指令的功能与其对应的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
section 指令
可以使用@hasSection
指令检查某个section是否包含内容:
@hasSection('navigation')
<div class="pull-right">
@yield('navigation')
</div>
<div class="clearfix"></div>
@endif
我们可以使用sectionMissing
指令来确定某个section是否不包含内容:
@sectionMissing('navigation')
<div class="pull-right">
@include('default-navigation')
</div>
@endif
Environment 指令
我们可以使用@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
switch 语句
switch语句可以使用@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
循环时,我们可以使用loop变量来获取有关循环的信息,例如我们是否处于循环的第一次还是最后一次迭代中。
使用循环时,我们也可以结束循环或跳过当前循环:
@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
Loop变量
循环时,$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
如果我们处于嵌套循环中,则可以通过$loop的parent属性访问父循环的变量:
@foreach ($users as $user)
@foreach ($user->posts as $post)
@if ($loop->parent->first)
This is first iteration of the parent loop.
@endif
@endforeach
@endforeach
$loop变量还包含各种其他有用的属性:
属性 | 描述 |
---|---|
$loop->index | 当前循环迭代的索引(从0开始)。 |
$loop->iteration | 当前循环迭代(从1开始)。 |
$loop->remaining | 迭代仍保留在循环中。 |
$loop->count | 数组中要迭代的项目总数。 |
$loop->first | 这是否是循环中的第一次迭代。 |
$loop->last | 这是否是循环中的最后一次迭代。 |
$loop->even | 这是否是循环中的均匀迭代。 |
$loop->odd | 这是否是循环中的奇数次迭代。 |
$loop->depth | 当前循环的嵌套级别。 |
$loop->parent | 在嵌套循环中,父级的循环变量。 |
注释
Blade还允许我们在视图使用注释。但是,与HTML注释不同,Blade注释不包含在应用程序返回的HTML中:
{{-- This comment will not be present in the rendered HTML --}}
PHP
在某些情况下,将PHP代码嵌入视图中是不可避免的。可以使用Blade的@php
指令在模板中执行一个纯PHP代码块:
@php
//
@endphp
尽管Blade提供了此功能,但频繁使用它可能表明您模板中嵌入了太多逻辑。可能需要优化我们的代码了
@once指令
@once
指令允许我们定义模板的一部分,每次渲染周期仅执行一次。这对于使用stack将给定的JavaScript片段推入页面的header可能很有用。例如,如果要在循环中渲染给定的组件,则可能希望仅在首次渲染该组件时将JavaScript放入header:
@once
@push('scripts')
<script>
// Your custom JavaScript...
</script>
@endpush
@endonce