热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Laravel5.5视图Blade模板引擎

Blade简介Blade是由Laravel提供的非常简单但功能强大的模板引擎,不同于其他流行的PHP模板引擎,Blade在视图中并不约束你使用PHP原生代码。所有的Blade视图最

Blade 简介

Blade 是由 Laravel 提供的非常简单但功能强大的模板引擎,不同于其他流行的 PHP 模板引擎,Blade 在视图中并不约束你使用 PHP 原生代码。所有的 Blade 视图最终都会被编译成原生 PHP 代码并缓存起来直到被修改,这意味着对应用的性能而言 Blade 基本上是零开销。

Blade 视图文件(也叫模板文件)使用 .blade.php 文件扩展名,都存放在 resources/views 目录下。

模板继承

定义布局

使用 Blade 的两个最大优点是模板继承和片段组合,开始之前让我们先看一个例子。

首先,我们测试主页面布局,由于大多数 Web 应用在不同页面中使用同一个布局,可以很方便的将这个布局定义为一个单独的 Blade 页面。

在 resources/views/layouts 目录中,创建一个布局文件 layout.blade.php,内容如下:






@section('sidebar')
这里是侧边栏
@show


@yield('content')


该文件包含典型的 HTML 标记,不过,注意 @section 和 @yield 指令,前者定义了一个内容片段,而后者用于显示给定片段的内容。

现在我们已经为应用定义了一个布局,接下来定义继承该布局的子页面。

继承布局

定义子页面时,可以使用 Blade 的 @extends 指令来指定子页面所继承的布局,继承一个 Blade 布局的视图可以使用 @section 指令注入内容到布局定义的内容片段中。

如上面例子所示,这些片段的内容将会显示在布局中使用 @yield 的地方。

在 resources/views 目录中,创建视图文件 child.blade.php,内容如下:

@extends('layouts.layout')
@section('title', '视图标题')
@section('sidebar')
@parent

这是子页面的内容


@endsection
@section('content')

这里是主体内容,完善中...


@endsection

在本例中,sidebar 片段使用 @parent 指令来追加(而非覆盖)内容到布局的侧边栏,@parent 指令在视图渲染时将会被布局中的内容替换。

然后,在 routes/web.php 中定义路由以便访问该视图。

Route::get('blade', function () {
return view('child');
});

在浏览器中访问 http://www.adm.devp/blade ,查看显示效果。

组件&插槽

组件和插槽给内容片段(section)和布局(layout)带来了方便,不过,有些人可能会发现组件和插槽的模型更容易理解。

首先,我们假设有一个可复用的“alert”组件,我们想要在整个应用中都可以复用它。

创建 resources/views/alert.blade.php 文件,内容如下:


{
{ $slot }}

{ { $slot }} 变量包含了我们想要注入组件的内容,现在,要构建这个组件,我们可以使用 Blade 指令 @component。

@component('alert')
Whoops! Something went wrong!
@endcomponent

有时,为组件定义多个插槽很有用。下面我们来编辑 alert 组件。

修改 resources/views/alert.blade.php 文件:


{
{ $title }}

{
{ $slot }}

现在,我们可以使用指令 @slot 注入内容到命名的插槽。任何不在 @slot 指令中的内容都会被传递到组件的 $slot 变量中。

@component('alert')
@slot('title')
Forbidden
@endslot
You are not allowed to access this resource!
@endcomponent

这段代码的意思是通过组件名 alert 去查找对应的视图文件,装载到当前视图,然后通过组件中 @slot 定义的插槽内容去渲染插槽视图中对应的插槽位,如果组件没有为某个插槽位定义对应的插槽内容片段,则组件中的其他不在 @slot 片段中的内容将会用于渲染该插槽位,如果没有其他多余内容则对应插槽位为空。

传递额外数据到组件

有时,你可能需要传递额外数据到组件,出于这个原因,你可以传递数组数据作为第二个参数到 @component 指令,所有数据都会在组件模板中以变量方式生效:

@component('alert', ['foo' => 'bar'])
...
@endcomponent

数据显示

可以通过两个花括号包裹变量的形式,来显示传递到视图的数据。

比如,如果给出如下路由:

Route::get('greeting', function () {
return view('welcome', ['name' => 'jack']);
});

在视图文件中,显示 name 变量的内容:

{
{ $name }}

你还可以在视图文件中输出任何 PHP 函数的结果,实际上,可以将任何 PHP 代码放到 Blade 模板中:

The current UNIX timestamp is {
{ time() }}.

注:Blade 的 { { }} 语句已经经过 PHP 的 htmlentities 函数处理以避免 XSS 攻击。

输出存在的数据

有时候你想要输出一个变量,但是不确定该变量是否被设置,我们可以通过如下 PHP 代码:

{ isset($name) ? $name : 'Default' }}

除了使用三元运算符,Blade 还提供了更简单的方式:

{
{ $name or 'Default' }}

在本例中,如果 $name 变量存在,其值将会显示,否则将会显示 Default。

显示原生数据

默认情况下,Blade 的 { { }} 语句已经通过 PHP 的 htmlentities 函数处理以避免 XSS 攻击,如果你不想要数据被处理,比如要输出带 HTML 元素的富文本,可以使用如下语法:

Hello, {!! $name !!}.

注:输出用户提供的内容时要当心,对用户提供的内容总是要使用双花括号包裹以避免直接输出 HTML 代码。

渲染 JSON 内容

有时,你可能会将数据以数组方式传递到视图再将其转化为 JSON 格式以便初始化某个 Javascript 变量,例如:

这样显得很麻烦,有更简便的方式来实现这个功能,那就是 Blade 的 @json 指令:

Blade & Javascript 框架

由于很多 Javascript 框架也是用花括号来表示要显示在浏览器中的表达式,如 Vue,我们可以使用 @ 符号来告诉 Blade 引擎该表达式应该保持原生格式不作改动。比如:

Laravel


Hello, @{
{ name }}.

在本例中,@ 符号在编译阶段会被 Blade 移除,但是,{ { name }} 表达式将会保持不变,从而可以被 Javascript 框架正常渲染。

@verbatim指令

如果你在模板中有很大一部分篇幅显示 Javascript 变量,那么可以将这部分 HTML 封装在 @verbatim 指令中,这样就不需要在每个 Blade 输出表达式前加上 @ 前缀。

@verbatim


Hello, {
{ name }}.

@endverbatim

流程控制

除了模板继承和数据显示之外,Blade 还为常用的 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 还提供了 @isset 和 @empty 指令,分别对应 PHP 的 isset 和 empty 方法:

@isset($records)
// $records is defined and is not null...
@endisset
@empty($records)
// $records is "empty"...
@endempty

认证指令

@auth 和 @guest 指令可用于快速判断当前用户是否登录:

@auth
// 用户已登录...
@endauth
@guest
// 用户未登录...
@endguest

如果需要的话,你也可以在使用 @auth 和 @guest 的时候指定登录用户类型:

@auth('admin')
// The user is authenticated...
@endauth
@guest('admin')
// The user is not authenticated...
@endguest

关于用户登录认证我们后面再讲到用户认证的时候再深入探讨。

Switch 语句

switch 语句可以通过 @switch,@case,@break,@default 和 @endswitch 指令构建:

@switch($i)
@case(1)
First case...
@break
@case(2)
Second case...
@break
@default
Default case...
@endswitch

循环语句

Blade 还提供了简单的指令用于处理 PHP 的循环结构。

@for ($i = 0; $i <10; $i++)
The current value is {
{ $i }}
@endfor
@foreach ($users as $user)

This is user {
{ $user->id }}


@endforeach
@forelse ($users as $user)
  • {
    { $user->name }}

  • @empty

    No users


    @endforelse
    @while (true)

    I'm looping forever.


    @endwhile

    注:在循环的时候可以使用 $loop 变量获取循环信息,例如是否是循环的第一个或最后一个迭代。

    使用循环的时候还可以结束循环或跳出当前迭代:

    @foreach ($users as $user)
    @if ($user->type == 1)
    @continue
    @endif

  • {
    { $user->name }}

  • @if ($user->number == 5)
    @break
    @endif
    @endforeach

    还可以使用指令声明来引入条件:

    @foreach ($users as $user)
    @continue($user->type == 1)

  • {
    { $user->name }}

  • @break($user->number == 5)
    @endforeach

    $loop 变量

    在循环的时候,可以在循环体中使用 $loop 变量,该变量提供了一些有用的信息,比如当前循环索引,以及当前循环是不是第一个或最后一个迭代:

    @foreach ($users as $user)
    @if ($loop->first)
    This is the first iteration.
    @endif
    @if ($loop->last)
    This is the last iteration.
    @endif

    This is user {
    { $user->id }}


    @endforeach

    如果是嵌套循环,可以通过 $loop 变量的 parent 属性访问父级循环:

    @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嵌套循环中的父级循环变量

    注释

    Blade 还允许你在视图中定义注释,然而,不同于 HTML 注释,Blade 注释并不会包含到 HTML 中被返回:

    {
    {-- This comment will not be present in the rendered HTML --}}

    嵌入原生 PHP 代码

    在一些场景中,嵌入 PHP 代码到视图中很有用,你可以使用 @php 指令在模板中执行一段原生 PHP 代码:

    @php
    //
    @endphp

    注:尽管 Blade 提供了这个特性,如果过于频繁地使用它意味着你在视图模板中嵌入了过多的业务逻辑,需要注意。

    包含子视图

    Blade 的 @include 指令允许你很轻松地在一个视图中包含另一个 Blade 视图,所有父级视图中的变量在被包含的子视图中依然有效:


    @include('shared.errors')



    上述指令会在当前目录下的 shared 子目录中寻找 errors.blade.php 文件并将其内容引入当前视图。

    尽管被包含的视图可以继承所有父视图中的数据,你还可以传递额外参数到被包含的视图:

    @include('view.name', ['some' => 'data'])

    当然,如果你尝试包含一个不存在的视图,Laravel 会抛出错误,如果你想要包含一个有可能不存在的视图,可以使用 @includeIf 指令:

    @includeIf('view.name', ['some' => 'data'])

    如果包含的视图取决于一个给定的布尔条件,可以使用 @includeWhen 指令:

    @includeWhen($boolean, 'view.name', ['some' => 'data'])

    要包含给定数组中的第一个视图,可以使用 @includeFirst 指令:

    @includeFirst(['custom.admin', 'admin'], ['some' => 'data'])

    注:不要在 Blade 视图中使用 __DIR__ 和 __FILE__ 常量,因为它们会指向缓存视图的路径。

    渲染集合视图

    可以使用 Blade 的 @each 指令通过一行代码循环引入多个局部视图:

    @each('view.name', $jobs, 'job')

    该指令的第一个参数是数组或集合中每个元素要渲染的局部视图,第二个参数是你希望迭代的数组或集合,第三个参数是要分配给当前视图的变量名。

    举个例子,如果你要迭代一个 jobs 数组,通常你需要在局部视图中访问 $job 变量。在局部视图中可以通过 key 变量访问当前迭代的键。

    你还可以传递第四个参数到 @each 指令,该参数用于指定给定数组为空时渲染的视图:

    @each('view.name', $jobs, 'job', 'view.empty')

    堆栈

    Blade 允许你推送内容到命名堆栈,以便在其他视图或布局中渲染。这在子视图中引入指定 Javascript 库时很有用:

    @push('scripts')

    @endpush

    推送次数不限,要渲染完整的堆栈内容,传递堆栈名称到 @stack 指令即可:



    @stack('scripts')

    服务注入

    @inject 指令可以用于从服务容器中获取服务,传递给 @inject 的第一个参数是服务对应的变量名,第二个参数是要解析的服务类名或接口名:

    @inject('metrics', 'App\Services\MetricsService')


    Monthly Revenue: {
    { $metrics->monthlyRevenue() }}.

    扩展 Blade

    Blade 甚至还允许你自定义指令,可以使用 directive 方法来注册一个指令。当 Blade 编译器遇到该指令,将会传入参数并调用提供的回调。

    下面的例子创建了一个 @datetime($var) 指令格式化给定的 DateTime 的实例 $var:

    namespace App\Providers;
    use Illuminate\Support\Facades\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 "";
    });
    }
    /**
    * 在容器中注册绑定.
    *
    * @return void
    */
    public function register()
    {
    //
    }
    }

    在视图文件中使用该自定义指令:

    @datetime(1508888888)

    注:更新完 Blade 指令逻辑后,必须删除所有的 Blade 缓存视图。缓存的 Blade 视图可以通过 Artisan 命令 view:clear 移除。

    自定义 if 语句

    在定义一些简单、自定义的条件语句时,编写自定义指令往往复杂性大于必要性,因为这个原因,Blade 提供了一个 Blade::if 方法通过闭包的方式快速定义自定义的条件指令,例如,我们来自定义一个条件来检查当前应用的环境,我们可以在 AppServiceProvider 的 boot 方法中定义这段逻辑。

    use Illuminate\Support\Facades\Blade;
    /**
    * Perform post-registration booting of services.
    *
    * @return void
    */
    public function boot()
    {
    \Blade::if('env', function ($environment) {
    return app()->environment($environment);
    });
    }

    定义好自定义条件后,就可以在模板中使用了:

    @env('local')
    The application is in the local environment...
    @else
    The application is not in the local environment...
    @endenv

    推荐阅读
    • 依赖注入_php 依赖注入容器
      篇首语:本文由编程笔记#小编为大家整理,主要介绍了php依赖注入容器相关的知识,希望对你有一定的参考价值。原文: http://blog.csdn.net/r ... [详细]
    • vue使用
      关键词: ... [详细]
    • 基于layUI的图片上传前预览功能的2种实现方式
      本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
    • Voicewo在线语音识别转换jQuery插件的特点和示例
      本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
    • 本文介绍了绕过WAF的XSS检测机制的方法,包括确定payload结构、测试和混淆。同时提出了一种构建XSS payload的方法,该payload与安全机制使用的正则表达式不匹配。通过清理用户输入、转义输出、使用文档对象模型(DOM)接收器和源、实施适当的跨域资源共享(CORS)策略和其他安全策略,可以有效阻止XSS漏洞。但是,WAF或自定义过滤器仍然被广泛使用来增加安全性。本文的方法可以绕过这种安全机制,构建与正则表达式不匹配的XSS payload。 ... [详细]
    • 如何提高PHP编程技能及推荐高级教程
      本文介绍了如何提高PHP编程技能的方法,推荐了一些高级教程。学习任何一种编程语言都需要长期的坚持和不懈的努力,本文提醒读者要有足够的耐心和时间投入。通过实践操作学习,可以更好地理解和掌握PHP语言的特异性,特别是单引号和双引号的用法。同时,本文也指出了只走马观花看整体而不深入学习的学习方式无法真正掌握这门语言,建议读者要从整体来考虑局部,培养大局观。最后,本文提醒读者完成一个像模像样的网站需要付出更多的努力和实践。 ... [详细]
    • 如何用JNI技术调用Java接口以及提高Java性能的详解
      本文介绍了如何使用JNI技术调用Java接口,并详细解析了如何通过JNI技术提高Java的性能。同时还讨论了JNI调用Java的private方法、Java开发中使用JNI技术的情况以及使用Java的JNI技术调用C++时的运行效率问题。文章还介绍了JNIEnv类型的使用方法,包括创建Java对象、调用Java对象的方法、获取Java对象的属性等操作。 ... [详细]
    • 本文介绍了PHP常量的定义和使用方法,包括常量的命名规则、大小写敏感性、全局范围和标量数据的限制。同时还提到了应尽量避免定义resource常量,并给出了使用define()函数定义常量的示例。 ... [详细]
    • 本文介绍了在go语言中利用(*interface{})(nil)传递参数类型的原理及应用。通过分析Martini框架中的injector类型的声明,解释了values映射表的作用以及parent Injector的含义。同时,讨论了该技术在实际开发中的应用场景。 ... [详细]
    • Spring框架《一》简介
      Spring框架《一》1.Spring概述1.1简介1.2Spring模板二、IOC容器和Bean1.IOC和DI简介2.三种通过类型获取bean3.给bean的属性赋值3.1依赖 ... [详细]
    • UNIX高级环境编程 第11、12章 线程及其属性
      第11章线程11.2线程概念线程资源:线程ID,一组寄存器,栈,调度优先级和策略,信号屏蔽字,e ... [详细]
    • 浅解XXE与Portswigger Web Sec
      XXE与PortswiggerWebSec​相关链接:​博客园​安全脉搏​FreeBuf​XML的全称为XML外部实体注入,在学习的过程中发现有回显的XXE并不多,而 ... [详细]
    • zuul 路由不生效_Zuul网关到底有何牛逼之处?竟然这么多人在用~
      作者:kosamino来源:cnblogs.comjing99p11696192.html哈喽,各位新来的小伙伴们,大家好& ... [详细]
    • InterfaceAsSchematic接口就是大纲接口在开发程序的“骨架”时非常有用。在设计组件时,使用接口进行设计和讨论都是对你的团队有益处的。比如定义一个BillingNot ... [详细]
    • 上一章我们设置了分类页面的页面标签,这一章我们继续标签设置格局。话不多说标签设置格局,我们一起操练起来吧~ ... [详细]
    author-avatar
    木木爱上林
    这个家伙很懒,什么也没留下!
    PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
    Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有