Blade 模板引擎入门篇
1、Blade 概述
与视图文件紧密关联的就是模板代码,我们在视图文件中通过模板代码和 HTML 代码结合实现视图的渲染。和很多其他后端语言不同,PHP 本身就可以当做模板语言来使用,但是这种方式有很多缺点,比如安全上的隐患、容易产生业务逻辑与视图模板的耦合,而且在视图文件中到处使用 <?php
内联代码一点都不优雅,甚至是 ugly code,所以你会看到绝大多数现代框架都会提供一套模板引擎,比如 Smarty,Twig,以及 Laravel 使用的 Blade。
注:不同于其他基于 Symfony 的 PHP 框架,Laravel 没有使用 Twig 模板引擎,不过你想要使用的话,可以借助 TwigBridge 扩展包来实现。
Blade 模板引擎是由 Laravel 框架提供的自有实现,借鉴了 .NET 的 Razor 引擎语法,其语法简洁,易于上手,同时提供了强大而直观的继承模型,而且方便扩展。下面是一个简单的 Blade 模板代码示例:
<h1>{{ $group->title }}</h1>
{!! $group->imageHtml() !!}
@forelse ($users as $user)
{{ $user->username }} {{ $user->nickname }}<br>
@empty
该组中没有任何用户
@endforelse
正如你所看到的,Blade 模板引擎有三种常见的语法:
- 通过
{{ }}
渲染 PHP 变量(最常用) - 通过
{!! !!}
渲染原生 HTML 代码(用于富文本数据渲染) - 通过以
@
作为前缀的 Blade 指令执行一些控制结构和继承、引入之类的操作
下面我们就来逐一介绍这些语法。
注:Blade 模板代码存放在以
.blade.php
后缀结尾的视图文件中,最终会被编译为原生 PHP 代码,并缓存起来,直到视图模板有修改才会再次编译,所以拥有与原生 PHP 几乎一致的性能,这些编译后的代码位于storage/framework/views
目录下。你当然可以在 Blade 模板中使用原生 PHP 代码,但是不建议这么做,如果你非要这么做的话,可以通过 @php 指令引入。
2、渲染数据
首先我们来看一下 {{}} 语法,我们通过通过该语法包裹需要渲染的 PHP 变量,如 {{ variable }},你可以将其类比为
<?php echo
<?php echo htmlentities($variable); ?>
但是某些情况下不能对变量中 HTML 字符进行转义,比如我们在表单通过富文本编辑器编辑后提交的表单数据,这种场景就需要通过 {!! !!}
来包裹待渲染数据了:
{!! $variable !!}
这样编译后的代码就是 <?php echo $variable; ?>
了。
注:对于富文本数据 XSS 攻击防护,可以参考这篇教程:https://xueyuanjun.com/post/9476.html
最后,关于数据变量渲染,我们还要注意的是,很多前端框架也是通过 {{}}
来输出 JavaScript 变量数据的,比如 Laravel 的好基友 Vue.js 就是,对于这种情况,我们需要在渲染前端 JavaScript 变量的 {{}}
前面加上 @
前缀,这样,Blade 模板引擎在编译模板代码的时候会跳过带 @
前缀的 {{}}
数据渲染,并将 @
移除从而可以后续执行对应的 JavaScript 框架渲染逻辑:
// Blade 引擎会将其编译为对应的 PHP 代码
{{ $phpData }}
// Blade 引擎编译时会移除 @,保留 {{ $vueData }} 结构
@{{ $vueData }}
如果要注释一段 PHP 代码,可以通过 {{-- 注释内容 --}}
实现。
3、控制结构
Blade 中的控制结构语法和 PHP 大同小异,学习成本几乎为零,不过 Blade 为我们额外提供了一些有用的辅助变量和方法,方便我们进行条件判断。
条件语句
@if、@else、@elseif
Blade 模板中的 @if
等价于 PHP 的 <?php if ($condition):
,@else
和 @elseif
依次类推,最后以一个 @endif
收尾:
@if (count($students) === 1)
操场上只有一个同学
@elseif (count($students) === 0)
操场上一个同学也没有
@else
操场上有 {{ count($students) }} 个同学
@endif
和原生 PHP 中的用法如出一辙。
@unless
@unless 是 Blade 提供的一个 PHP 中没有的语法,用于表示和 @if 条件相反的条件,@unless(condition) 可以理解为 <?php if (!
@unless ($user->hasPaid())
用户没有支付
@endunless
@isset、@empty
这两个指令和 PHP 中的 isset()
和 empty()
方法等价:
@isset($records)
// 记录被设置
@endisset
@empty($records)
// 记录为空
@endempty
后面两个都是语法糖,如果你不想记太多东西,不防都用 @if
来实现对应的逻辑了。
@switch
顾名思义,Blade 中的 @switch
指令和 PHP 中的 switch
语句等价,我们可以通过 @switch
、@case
、@break
、@default
和 @endswitch
指令构建对应逻辑:
@switch($i)
@case(1)
// $i = 1 做什么
@break
@case(2)
// $i = 2 做什么
@break
@default
// 默认情况下做什么
@endswitch
循环结构
@for、@foreach 和 @while
和 PHP 一样,在 Laravel 中,我们可以通过与之等价的 @for
、@foreach
和 @while
实现循环控制结构,使用语法和 PHP 代码相仿:
// for 循环
@for ($i = 0; $i < $talk->slotsCount(); $i++)
The number is {{ $i }}<br>
@endfor
// foreach 循环
@foreach ($talks as $talk)
{{ $talk->title }} ({{ $talk->length }} 分钟)<br>
@endforeach
// while 循环
@while ($item = array_pop($items))
{{ $item->orSomething() }}<br>
@endwhile
@forelse
这个指令是 PHP 中具备的,可以理解为处理以下 PHP 代码逻辑:
<?php
if ($students) {
foreach ($students as $student) {
// do something ...
}
} else {
// do something else ...
}
在 Blade 模板中我们可以使用 @forelse
指令通过以下代码实现上述逻辑:
@forelse ($students as $student)
// do something ...
@empty
// do something else ...
@endforelse
@foreach 和 @forelse 中的 $loop 变量
在循环控制结构中,我们要重磅介绍的就是 Blade 模板为@foreach
和@forelse
循环结构提供的$loop
变量了,通过该变量,我们可以在循环体中轻松访问该循环体的很多信息,而不用自己编写那些恼人的面条式代码,比如当前迭代索引、嵌套层级、元素总量、当前索引在循环中的位置等,$loop
实例上有以下属性可以直接访问:
下面是一个简单的使用示例:
<ul>
@foreach ($pages as $page)
@if ($loop->first)
// 第一个循环迭代
@endif
<li>{{ $loop->iteration }}: {{ $page->title }}
@if ($page->hasChildren())
<ul> @foreach ($page->children() as $child)
<li>{{ $loop->parent->iteration }}. {{ $loop->iteration }}: {{ $child->title }}</li>
@endforeach
</ul>
@endif
</li>
@if ($loop->last)
// 最后一个循环迭代
@endif
@endforeach
</ul>
有了这个 $loop
变量,确实能够帮我们节省很多重复的逻辑判断和编码工作,推荐使用。
(全文完)
- 克隆虚拟机的注意点
- keepalived+nginx搭建高可用(注意点)
- 我的WCF之旅(10):如何在WCF进行Exception Handling
- 安装nginx出现的问题
- 18.11 LVS DR模式搭建
- Linux基础(day64)
- 我的WCF之旅(9):如何在WCF中使用tcpTrace来进行Soap Trace
- 物联网设备已沦陷,咖啡机也不能例外
- 我的WCF之旅(13):创建基于MSMQ的Responsive Service
- 开发自己的Data Access Application Block[上篇]
- 18.9/18.10 LVS NAT模式搭建
- 谈谈WCF中的Data Contract (1):Data Contract Overview
- Linux基础(day66)
- 字符串的驻留(String Interning)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Nginx安装与使用
- 基于Redis实现分布式锁
- 通过简单代码示例了解七大软件设计原则
- Flink在新浪微博的在线机器学习和实时数据分析
- Nginx + Keepalived使用文档
- 22+ 高频实用的 JavaScript 片段 (2020年)
- 文件上传C:fakepath解决方案
- Asp.net web api部署在某些服务器上老是404
- Spring解决循环依赖的思路
- Spring中Bean的创建流程
- 详解RocketMQ事务消息
- 带你白嫖程序带宽限制命令Trickle
- Fix SSH客户端登录会话超时设置
- JAVA的泛型与反射的联合应用
- 专项测试实战 | 如何测试 App 流畅度(基于 FPS 和丢帧率)