[TOC]
### **1、简介**
[Blade](http://laravelacademy.org/tags/blade "View all posts in Blade") 是 [Laravel](http://laravelacademy.org/tags/laravel "View all posts in Laravel") 提供的一个非常简单但很强大的[模板引擎](http://laravelacademy.org/tags/%e6%a8%a1%e6%9d%bf%e5%bc%95%e6%93%8e "View all posts in 模板引擎"),不同于其他流行的 [PHP](http://laravelacademy.org/tags/php "View all posts in PHP") 模板引擎,Blade 在[视图](http://laravelacademy.org/tags/%e8%a7%86%e5%9b%be "View all posts in 视图")中并不约束你使用 PHP 原生代码。所有的 Blade 视图都会被编译成原生 PHP 代码并缓存起来直到被修改,这意味着对应用的性能而言 Blade 基本上是零开销。Blade 视图文件使用 `.blade.php` 文件扩展并存放在 `resources/views` 目录下。
### **2、模板继承**
#### **定义[布局](http://laravelacademy.org/tags/%e5%b8%83%e5%b1%80 "View all posts in 布局")**
使用 Blade 的两个最大优点是模板继承和切片,开始之前让我们先看一个例子。首先,我们检测一个“主”页面布局,由于大多数 Web 应用在不同页面中使用同一个布局,可以很方便的将这个布局定义为一个单独的 Blade 页面:
~~~
<!-- 存放在 resources/views/layouts/master.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](http://laravelacademy.org/tags/html "View all posts in HTML") 标记,然而,注意 `@section` 和 `@yield` [指令](http://laravelacademy.org/tags/%e6%8c%87%e4%bb%a4 "View all posts in 指令"),前者正如其名字所暗示的,定义了一个内容的片段,而后者用于显示给定片段的内容。
现在我们已经为应用定义了一个布局,接下来让我们定义继承该布局的子页面吧。
#### **扩展布局**
定义子页面的时候,可以使用 Blade 的 `@extends` 指令来指定子页面所继承的布局,继承一个 Blade 布局的视图将会使用 `@section` 指令注入内容到布局的片段中,记住,如上面例子所示,这些片段的内容将会显示在布局中使用`@yield` 的地方:
~~~
<!-- 存放在 resources/views/child.blade.php -->
@extends('layouts.master')
@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` 指令来追加(而非覆盖)内容到布局中 `sidebar`,`@parent` 指令在视图渲染时将会被布局中的内容替换。
当然,和原生 PHP 视图一样,Blade 视图可以通过 `view` 方法直接从路由中返回:
~~~
Route::get('blade', function () {
return view('child');
});
~~~
### **3、数据显示**
可以通过两个花括号包裹变量来显示传递到视图的数据,比如,如果给出如下路由:
~~~
Route::get('greeting', function () {
return view('welcome', ['name' => 'Samantha']);
});
~~~
那么可以通过如下方式显示 `name` 变量的内容:
~~~
Hello, {{ $name }}.
~~~
当然,不限制显示到视图中的变量内容,你还可以输出任何 PHP 函数,实际上,可以将任何 PHP 代码放到 Blade 模板语句中:
~~~
The current UNIX timestamp is {{ time() }}.
~~~
> 注:Blade 的 `{{}}` 语句已经经过 PHP 的 `htmlentities` 函数处理以避免 [XSS](http://laravelacademy.org/tags/xss "View all posts in XSS") 攻击。
#### **Blade & JavaScript 框架**
由于很多 JavaScript 框架也是用花括号来表示要显示在浏览器中的表达式,可以使用 `@` 符号来告诉 Blade 渲染引擎该表达式应该保持原生格式不作改动。比如:
~~~
<h1>Laravel</h1>
Hello, @{{ name }}.
~~~
在本例中,`@` 符将会被 Blade 移除,然而,`{{ name }}` 表达式将会保持不变,避免被 JavaScript 框架渲染。
#### **输出存在的数据**
有时候你想要输出一个变量,但是不确定该变量是否被设置,我们可以通过如下 PHP 代码:
~~~
{{ isset($name) ? $name : 'Default' }}
~~~
除了使用三元运算符,Blade 还提供了更简单的方式:
~~~
{{ $name or 'Default' }}
~~~
在本例中,如果 `$name` 变量存在,其值将会显示,否则将会显示“Default”。
#### **显示原生数据**
默认情况下,Blade 的 `{{ }}` 语句已经通过 PHP 的 `htmlentities` 函数处理以避免 XSS 攻击,如果你不想要数据被处理,可以使用如下语法:
~~~
Hello, {!! $name !!}.
~~~
> 注:输出用户提供的内容时要当心,对用户提供的内容总是要使用双花括号包裹以避免直接输出 HTML 代码。
### **4、[流程控制](http://laravelacademy.org/tags/%e6%b5%81%e7%a8%8b%e6%8e%a7%e5%88%b6 "View all posts in 流程控制")**
除了模板继承和数据显示之外,Blade 还为常用的 PHP 流程控制提供了便利操作,比如条件语句和循环,这些快捷操作提供了一个干净、简单的方式来处理 PHP 的流程控制,同时保持和 PHP 相应语句的相似。
#### **If 语句**
可以使用 `@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
~~~
#### **循环**
除了条件语句,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
~~~
#### **包含子视图**
Blade 的 `@include` 指令允许你很简单的在一个视图中包含另一个 Blade 视图,所有父级视图中变量在被包含的子视图中依然有效:
~~~
<div>
@include('shared.errors')
<form>
<!-- Form Contents -->
</form>
</div>
~~~
尽管被包含的视图继承所有父视图中的数据,你还可以传递额外参数到被包含的视图:
~~~
@include('view.name', ['some' => 'data'])
~~~
> 注:不要在 Blade 视图中使用 `__DIR__` 和 `__FILE__` 常量,因为它们会指向缓存视图的路径。
#### **为[集合](http://laravelacademy.org/tags/%e9%9b%86%e5%90%88 "View all posts in 集合")渲染视图**
你可以使用 Blade 的 `@each` 指令通过一行代码循环引入多个局部视图:
~~~
@each('view.name', $jobs, 'job')
~~~
该指令的第一个参数是数组或集合中每个元素要渲染的局部视图,第二个参数是你希望迭代的数组或集合,第三个参数是要分配给当前视图的变量名。举个例子,如果你要迭代一个 `jobs` 数组,通常你需要在局部视图中访问 `$job` 变量。
你还可以传递第四个参数到 `@each` 指令,该参数用于指定给定数组为空时渲染的视图:
~~~
@each('view.name', $jobs, 'job', 'view.empty')
~~~
#### **[注释](http://laravelacademy.org/tags/%e6%b3%a8%e9%87%8a "View all posts in 注释")**
Blade 还允许你在视图中定义注释,然而,不同于 HTML 注释,Blade 注释并不会包含到 HTML 中被返回:
~~~
{{-- This comment will not be present in the rendered HTML --}}
~~~
### **5、服务注入**
`@inject` 指令可以用于从服务容器中获取服务,传递给 `@inject` 的第一个参数是服务将要被放置到的变量名,第二个参数是要解析的服务类名或接口名:
~~~
@inject('metrics', 'App\Services\MetricsService')
<div>
Monthly Revenue: {{ $metrics->monthlyRevenue() }}.
</div>
~~~
### **6、扩展 Blade**
Blade 甚至还允许你[自定义](http://laravelacademy.org/tags/%e8%87%aa%e5%ae%9a%e4%b9%89 "View all posts in 自定义")指令,可以使用 `directive` 方法来注册一个指令。当 Blade 编译器遇到该指令,将会传入参数并调用提供的回调。
下面的例子创建了一个 `@datetime($var)` 指令格式化给定的 `$var`:
~~~
<?php
namespace App\Providers;
use Blade;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Perform post-registration booting of services.
*
* @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'); ?>
~~~
- 序言
- 发行版本说明
- 升级指南
- 贡献代码
- 开始
- 安装
- 配置
- Laravel Homestead
- 基础
- HTTP 路由
- HTTP 中间件
- HTTP 控制器
- HTTP 请求
- HTTP 响应
- 视图
- Blade 模板引擎
- 架构
- 一次请求的生命周期
- 应用目录结构
- 服务提供者
- 服务容器
- 门面(Facades)
- 数据库
- 起步
- 查询构建器
- 迁移
- 填充数据
- Eloquent ORM
- 起步
- 关联关系
- 集合
- 访问器&修改器
- 序列化
- 服务
- 用户认证
- 用户授权
- Artisan Console
- 订阅支付实现:Laravel Cashier
- 缓存
- 集合
- 集成前端资源:Laravel Elixir
- 加密
- 错误&日志
- 事件
- 文件系统/云存储
- 哈希
- 辅助函数
- 本地化
- 邮件
- 包开发
- 分页
- Redis
- 队列
- Session
- Envoy Task Runner
- 任务调度
- 测试
- 验证
- 新手入门指南
- 简单任务管理系统
- 带用户功能的任务管理系统