一、什么是Blade模版?
Blade 是 Laravel 提供的一個既簡單又強大的模板引擎。
和其他流行的 PHP 模板引擎不一樣,Blade 並不限制你在視圖中使用原生 PHP 代碼。所有 Blade 視圖文件都將被編譯成原生的 PHP 代碼並緩存起來,除非它被修改,否則不會重新編譯,這就意味着 Blade 基本上不會給你的應用增加任何額外負擔。
Blade 視圖文件使用 .blade.php 擴展名,一般被存放在 resources/views 目錄。
像之前實驗中的 welcome.blade.php 和 home.blade.php 等都是 blade 模板文件,只是我們之前還沒有用到模板的功能,在本次實驗我們將體驗強大的 blade 模板功能。
二、模板繼承
模板繼承是最常用的一個 blade 模板功能。
平時訪問網站的時候,可以發現,一般一個網站的不同頁面都應該是類似的,比如都有相同的導航欄和底部信息欄,或者都有相同的左側菜單欄。
我們在寫代碼的時候不可能每個頁面都要把重復的東西寫一遍,這樣不僅效率低下,還不易維護,所以就有了模板繼承。
下面我們通過一個很簡單的例子來使用模板繼承。
首先,創建相關路由:
app/Http/routes.php
<?php
//home page
Route::get('/', 'StaticPagesController@home')->name('home');
//about page
Route::get('/about', 'StaticPagesController@about')->name('about');
然后,使用 artisan 創建控制器:
cd ~/Code/myweb
php artisan make:controller StaticPagesController --plain
打開控制器,創建相應方法:
app/Http/Controllers/StaticPagesController.php
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Http\Requests; use App\Http\Controllers\Controller; class StaticPagesController extends Controller { public function home() { return view('home'); } public function about() { return view('about'); } }
然后,在 resources/views 目錄下創建對應的視圖文件 home.blade.php和about.blade.php
打開這兩個視圖文件,分別輸入以下代碼:
resources/views/home.blade.php
<!DOCTYPE html>
<html>
<head>
<title>Home</title>
</head>
<body>
<h1>Home</h1>
<p>Welcome to My web</p>
</body>
</html>
resources/views/about.blade.php
<!DOCTYPE html>
<html>
<head>
<title>About</title>
</head>
<body>
<h1>About</h1>
<p>This is my first Laravel web</p>
<p>Author: SadCreeper</p>
<!-- 可以更改為你自己的信息 -->
</body>
</html>
然后,打開瀏覽器,輸入 localhost 和 localhost/about 可以看到我們創建的兩個視圖。
但是到現在為止,我們還沒有使用 blade 模板繼承,可以看到兩個視圖中有很多的重復代碼,下面創建一個基礎視圖,其他的所有視圖都將繼承這個基礎視圖。
在 resources/views 目錄下新建一個目錄 layouts 然后在 resources/views/layouts 目錄下新建一個視圖文件 app.blade.php。
打開這個 app.blade.php 加入如下代碼:
resources/views/layouts/app.blade.php
<!DOCTYPE html>
<html>
<head>
<title>Myweb</title>
</head>
<body>
@yield('content')
</body>
</html>
然后修改 home.blade.php 和 about.blade.php:
resources/views/home.blade.php
@extends('layouts.app')
@section('content')
<h1>Home</h1>
<p>Welcome to My web</p>
@endsection
resources/views/about.blade.php
@extends('layouts.app')
@section('content')
<h1>About</h1>
<p>This is my first Laravel web</p>
<p>Author: SadCreeper</p>
<!-- 可以更改為你自己的信息 -->
@endsection
其中頂部代碼:
@extends('layouts.app')
就是表示當前視圖繼承自 layouts 文件夾下的 app.blade.php 視圖。
然后用下面這種方式就可以把 section(‘content’) 中包含的內容放到被繼承的視圖 app.blade.php 中的 yield(‘content’) 部分。
@section('content')
//
@endsection
使用模板繼承后,你如果想對網站進行一些基礎的公用代碼的修改時,就可以修改 app.blade.php。
下面我們給這個基礎視圖添加一個非常簡單的頂部導航欄和底部信息欄。
resources/views/layouts/app.blade.php
<!DOCTYPE html>
<html>
<head>
<title>Myweb</title>
</head>
<body style="margin:0;padding:0;">
<!-- header -->
<div style="padding:10px 50px 10px 50px;border-bottom: 1px solid #eeeeee;">
<div style="display:inline-block;">
<a href="{{ route('home') }}"><h2>Myweb</h2></a>
</div>
<div style="display:inline-block;margin-left:20px;">
<a href="{{ route('about') }}">about</a>
</div>
</div>
<div style="text-align:center;">
@yield('content')
</div>
<!-- footer -->
<div style="padding:10px 50px 10px 50px;background-color:gray;">
<p>contact me : 1234567</p>
</div>
</body>
</html>
在本教程中,我把樣式寫到了 style 里,是為了簡化流程,通常來說,樣式代碼應該盡量寫到 css 文件中,以方便復用和維護。
此時我們訪問localhost 和 localhost/about 都可以看到完整的包含導航欄和底部信息欄的視圖。

二、引入子視圖
你可以使用 Blade 的 @include 命令來引入一個已存在的視圖,所有在父視圖的可用變量在被引入的視圖中都是可用的。
<div>
@include('shared.errors')
<form>
<!-- Form Contents -->
</form>
</div>
盡管被引入的視圖會繼承父視圖中的所有數據,你也可以通過傳遞額外的數組數據至被引入的頁面:
@include('view.name', ['some' => 'data'])
下面我們創建一個子視圖,用來顯示網站作者信息,你可以在網站上任何想顯示作者信息的地方引用這個視圖。
在 resources/views 目錄下新建一個文件夾 shared 然后在 resources/views/shared 目錄下新建一個文件 author.blade.php 打開該文件。
resources/views/shared/author.blade.php
<div style="width:200px;margin:20px auto 20px auto;padding:20px;border:1px solid black;">
<h3>Author</h3>
<p>name : SadCreeper</p>
<p>age : 22</p>
<p>Tel : 150-XXXX-XXXX</p>
</div>
然后在 resources/views/about.blade.php 中引用該子視圖:
resources/views/about.blade.php
@extends('layouts.app')
@section('content')
<h1>About</h1>
<p>This is my first Laravel web</p>
@include('shared.author')
@endsection
然后訪問localhost/about 看下效果:

此時如果你想在任何地方顯示這個子視圖,只需要在相應位置加入下面一行代碼即可~
@include('shared.author')
三、數據顯示
你可以使用 「中括號」 包住變量以顯示傳遞至 Blade 視圖的數據。如假設你有下面這樣一個路由:
Route::get('greeting', function () {
return view('welcome', ['name' => 'Samantha']);
});
你在視圖文件中可以像這樣顯示 name 變量的內容:
Hello, {{ $name }}.
你也可以顯示 PHP 函數的結果。事實上,你可以在 Blade 中顯示任意的 PHP 代碼:
The current UNIX timestamp is {{ time() }}.
有時候你可能想要輸出一個變量,但是你並不確定這個變量是否已經被定義,我們可以這樣:
{{ $name or 'Default' }}
在這個例子中,如果 $name 變量存在,它的值將被顯示出來。但是,如果它不存在,則會顯示 Default 。
在默認情況下,Blade 模板中的 {{ }} 表達式將會自動調用 PHP htmlentities 函數來轉義數據以避免 XSS 的攻擊。如果你不想你的數據被轉義,你可以使用下面的語法:
Hello, {!! $name !!}.
四、控制輸出
除了“模板繼承” 與 “數據顯示”的功能以外,Blade 也給一般的 PHP 結構控制語句提供了方便的縮寫,比如條件表達式和循環語句。這些縮寫提供了更為清晰簡明的方式來使用 PHP 的控制結構,而且還保持與 PHP 語句的相似性。
1.IF
你可以通過 @if , @elseif , @else 及 @endif 指令構建 if 表達式,這些命令的功能等同於在 PHP 中的語法:
@if (count($records) === 1)
我有一條記錄!
@elseif (count($records) > 1)
我有多條記錄!
@else
我沒有任何記錄!
@endif
為了方便,Blade 也提供了一個 @unless 命令:
@unless (Auth::check())
你尚未登錄。
@endunless
2.循環
@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
當循環進行時,你可以使用 循環變量 $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
如果你是在一個嵌套的循環中,你可以通過使用
@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->depth | 當前循環的嵌套深度。 |
| loop->parent | 當在嵌套的循環內時,可以訪問到父循環中的 $loop變量。 |
五、注釋
Blade 也允許在頁面中定義注釋,然而,跟 HTML 的注釋不同的是,Blade 注釋不會被包含在應用程序返回的 HTML 內:
{{-- 此注釋將不會出現在渲染后的 HTML --}}
六、包含子視圖
Blade的@include指令允許你很簡單的在一個視圖中包含另一個Blade視圖,所有父級視圖中變量在被包含的子視圖中依然有效:
<div>
@include('shared.errors')
<form>
<!-- Form Contents -->
</form>
</div>
盡管被包含的視圖繼承所有父視圖中的數據,你還可以傳遞額外參數到被包含的視圖:
@include('view.name', ['some' => 'data'])
七、服務注入
@inject指令可以用於從服務容器中獲取服務,傳遞給@inject的第一個參數是服務將要被放置到的變量名,第二個參數是要解析的服務類名或接口名:
@inject('metrics', 'App\Services\MetricsService') <div> Monthly Revenue: {{ $metrics->monthlyRevenue() }}. </div>
6、擴展Blade
Blade甚至還允許你自定義指令,可以使用directive方法來注冊一個指令。當Blade編譯器遇到該指令,將會傳入參數並調用提供的回調。
下面的例子創建了一個@datetime($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'); ?>
八、小結
用於封裝和繼承用的,還是比較實用的!!!
