热门标签 | 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

    推荐阅读
    • Windows 7 64位系统下Redis的安装与PHP Redis扩展配置
      本文详细介绍了在Windows 7 64位操作系统中安装Redis以及配置PHP Redis扩展的方法,包括下载、安装和基本使用步骤。适合对Redis和PHP集成感兴趣的开发人员参考。 ... [详细]
    • 深入理解 .NET 中的中间件
      中间件是插入到应用程序请求处理管道中的组件,用于处理传入的HTTP请求和响应。它在ASP.NET Core中扮演着至关重要的角色,能够灵活地扩展和自定义应用程序的行为。 ... [详细]
    • 本文详细介绍了优化DB2数据库性能的多种方法,涵盖统计信息更新、缓冲池调整、日志缓冲区配置、应用程序堆大小设置、排序堆参数调整、代理程序管理、锁机制优化、活动应用程序限制、页清除程序配置、I/O服务器数量设定以及编入组提交数调整等方面。通过这些技术手段,可以显著提升数据库的运行效率和响应速度。 ... [详细]
    • 深入解析Java虚拟机(JVM)架构与原理
      本文旨在为读者提供对Java虚拟机(JVM)的全面理解,涵盖其主要组成部分、工作原理及其在不同平台上的实现。通过详细探讨JVM的结构和内部机制,帮助开发者更好地掌握Java编程的核心技术。 ... [详细]
    • 微信小程序:授权登录与手机号绑定
      本文详细介绍了微信小程序中用户授权登录及绑定手机号的流程,结合官方指引和实际开发经验,提供了一套完整的实现方案,帮助开发者更好地理解和应用。 ... [详细]
    • ElasticSearch 集群监控与优化
      本文详细介绍了如何有效地监控 ElasticSearch 集群,涵盖了关键性能指标、集群健康状况、统计信息以及内存和垃圾回收的监控方法。 ... [详细]
    • 在编译BSP包过程中,遇到了一个与 'gets' 函数相关的编译错误。该问题通常发生在较新的编译环境中,由于 'gets' 函数已被弃用并视为安全漏洞。本文将详细介绍如何通过修改源代码和配置文件来解决这一问题。 ... [详细]
    • 本文探讨了如何通过预处理器开关选择不同的类实现,并解决在特定情况下遇到的链接器错误。 ... [详细]
    • 本文详细介绍了如何在PHP中进行数组删除、清空等操作,并提供了在Visual Studio Code中创建PHP文件的步骤。 ... [详细]
    • 本文深入探讨了面向切面编程(AOP)的概念及其在Spring框架中的应用。通过详细解释AOP的核心术语和实现机制,帮助读者理解如何利用AOP提高代码的可维护性和开发效率。 ... [详细]
    • 本文介绍如何从字符串中移除大写、小写、特殊、数字和非数字字符,并提供了多种编程语言的实现示例。 ... [详细]
    • 并发编程 12—— 任务取消与关闭 之 shutdownNow 的局限性
      Java并发编程实践目录并发编程01——ThreadLocal并发编程02——ConcurrentHashMap并发编程03——阻塞队列和生产者-消费者模式并发编程04——闭锁Co ... [详细]
    • 本文探讨了C++编程中理解代码执行期间复杂度的挑战,特别是编译器在程序运行时生成额外指令以确保对象构造、内存管理、类型转换及临时对象创建的安全性。 ... [详细]
    • 本文详细介绍了get和set方法的作用及其在编程中的实现方式,同时探讨了点语法的使用场景。通过具体示例,解释了属性声明与合成存取方法的概念,并补充了相关操作的最佳实践。 ... [详细]
    • 优化Flask应用的并发处理:解决Mysql连接过多问题
      本文探讨了在Flask应用中通过优化后端架构来应对高并发请求,特别是针对Mysql 'too many connections' 错误的解决方案。我们将介绍如何利用Redis缓存、Gunicorn多进程和Celery异步任务队列来提升系统的性能和稳定性。 ... [详细]
    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社区 版权所有