一、什么是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;">
<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
如果你是在一个嵌套的循环中,你可以通过使用 loop变量的parent属性来获取父循环中的loop变量的parent属性来获取父循环中的loop 变量:
@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'); ?>
八、小结
用于封装和继承用的,还是比较实用的!!!