[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
- 任務調度
- 測試
- 驗證
- 新手入門指南
- 簡單任務管理系統
- 帶用戶功能的任務管理系統