Blade 模板

收藏392

阅读118018

更新时间2022-04-15

前言:

Blade 模板

Blade 模板

简介

Blade 是 Laravel 提供的一个简单而又强大的模板引擎。和其他流行的 PHP 模板引擎不同,Blade 并不限制你在视图中使用原生 PHP 代码。所有 Blade 视图文件都将被编译成原生的 PHP 代码并缓存起来,除非它被修改,否则不会重新编译,这就意味着 Blade 基本上不会给你的应用增加任何负担。Blade 视图文件使用 .blade.php 作为文件扩展名,被存放在 resources/views 目录。

模板继承

定义布局

Blade 的两个主要优点是模板继承区块。为方便入门,让我们先通过一个简单的例子来上手。首先,我们来研究一个「主」页面布局。因为大多数 web 应用会在不同的页面中使用相同的布局方式,因此可以很方便地定义单个 Blade 布局视图:


   
       
   App Name - @yield('title')    
    
 
    @section('sidebar')
     This is the master sidebar.
     @show       
     
     @yield('content')       
      
      

如你所见,该文件包含了典型的 HTML 语法。不过,请注意 @section@yield 指令。 @section 指令定义了视图的一部分内容,而 @yield 指令是用来显示指定部分的内容。

现在,我们已经定义好了这个应用程序的布局,接下来,我们定义一个继承此布局的子页面。

扩展布局

在定义一个子视图时,使用 Blade 的 @extends 指令指定子视图要「继承」的视图。扩展自 Blade 布局的视图可以使用 @section 指令向布局片段注入内容。就如前面的示例中所示,这些片段的内容将由布局中的显示在布局中 @yield 指令控制显示:


@extends('layouts.app')
@section('title', 'Page Title')
@section('sidebar')
    @parent    
    

This is appended to the master sidebar.

    @endsection @section('content')     

This is my body content.

@endsection

在这个示例中, sidebar 片段利用 @parent 指令向布局的 sidebar 追加(而非覆盖)内容。 在渲染视图时,@parent 指令将被布局中的内容替换。

{tip} 和上一个示例相反,这里的  sidebar 片段使用  @endsection 代替 @show 来结尾。 @endsection 指令仅定义了一个片段, @show 则在定义的同时 立即 yield 这个片段。

Blade 视图可以使用全局  view 助手自路由中返回:

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

组件 & 插槽

组件和插槽提供了与片段和布局类似的好处;不过组件和插槽的思维模型更易于理解。我们先来看一个可复用的「alert」组件,我们想在应用中复用它:


   
 {{ $slot }}

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

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

有时候为一个组件定义多个插槽是很有用的。修改 alert 组件以允许其注入 「title」。命名插槽可以通过与其匹配的 「回显」 变量显示:


  
  {{ $title }}
       {{ $slot }}  

现在,我们能够使用 @slot 指令向命名插槽注入内容。不在  @slot 指令内的内容都将传递给组件中的  $slot 变量:

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

向组件传递额外的数据

有时你可能需要向组件传递额外的数据。在这种情况下,可以把包含数据组织成数组,作为 @component 指令的第二个参数。所有的数据将作为变更提供给组件模板:

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

给组件起别名

如果组件存储在子目录中,你可能希望给它们起个别名以方便访问。举例来说,如果一个 Blade 组件存储在 resources/views/components/alert.blade.php 中,. 就可以使用 component 方法将 components.alert 的别名命名为 alert。. 通常情况下,这一过程将在 AppServiceProvider 的  boot 方法中完成:

use Illuminate\Support\Facades\Blade;
Blade::component('components.alert', 'alert');

一旦组件有了别名,就可以使用一条指令渲染它:

@alert(['type' => 'danger'])
    You are not allowed to access this resource!@endalert

如果没有额外的插槽,还可以省略组件参数:

@alert
    You are not allowed to access this resource!@endalert

显示数据

可以通过包裹在双花括号内的变量显示传递给 Blade 视图的数据。比如给出如下路由:

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

就可以这样利用 name 变量显示其内容:

Hello, {{ $name }}.

{tip} Blade {{ }} 语句是自动经过  PHP 的 htmlspecialchars 函数传递来防范  XSS 攻击的。

不限于显示传递给视图的变量的内容,你还可以显示任一 PHP 函数的结果。实际上,你可以在 Blade 的回显语句中放置你想要的任意 PHP 代码:

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

显示非转义字符

默认情况下, Blade 中 {{ }} 语句自动经由 PHP 的 htmlspecialchars 函数传递以防范 XSS 攻击。如果不希望数据被转义,可以使用下面的语法:

Hello, {!! $name !!}.

{note} 在回显应用的用户提供的内容时需要谨慎小心。在显示用户提供的数据时,有必要一直使用双花括号语法转义来防范 XSS 攻击。

渲染 JSON

有时,为了初始化一个 JavaScript 变量,你可能会向视图传递一个数据,并将其渲染成 JSON:

不过,你可以使用 @json Blade 指令代替手动调用 json_encode 函数:

HTML 实体编码

默认情况下,Blade (以及 Laravel 的 e 助手)将对 HTML 实体双重编码。如果要禁用双重编码,可以在 AppServiceProviderboot 中调用 Blade::withoutDoubleEncoding 方法:

Blade & JavaScript 框架

由于很多 JavaScript 框架也使用花括号表明给定的表达式将要在浏览器中显示, 可以使用 @ 符号通知 Blade 渲染引擎某个表达式应保持不变。示例如下:

Laravel

Hello, @{{ name }}.

在这个例子中, @ 符号将被 Blade 删除;在 Blade 引擎中 {{ name }} 表达式将保持不变,取而代之的是 JavaScript 引擎将渲染该表达式。

@verbatim 指令

如果要在大段的模板中 JavaScript 变量,可以将 HTML 包裹在 @verbatim 指令中,这样就不需要为每个 Blade 回显语句添加 @ 符号:

@verbatim   
 
        Hello, {{ name }}.  
  
@endverbatim

控制结构

除了模板继承和数据显示, Blade 还为分支和循环等 PHP 控制结构提供了方便的快捷方式。这些快捷方式提供了干净、简捷地处理 PHP 控制结构的方法,同时保持了与 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

除了已经讨论过的条件指令, @isset@empty 指令可以作为各自对应的 PHP 函数的快捷方式:

@isset($records) 
   // $records 被定义且不是 null...
@endisset

@empty($records)   
 // $records 为空...
@endempty

身份验证指令

@auth@guest 指令能够用于快速确定当前用户是经过身份验证的,还是一个访客:

@auth    // 此用户身份已验证...@endauth
@guest    // 此用户身份未验证...@endguest

如果需要,可以在使用 @auth@guest 指令时指定应被校验的 身份 :

@auth('admin')    // 此用户身份已验证...@endauth
@guest('admin')    // 此用户身份未验证...@endguest

片段指令

可以使用 @hasSection 指令检查片断是否存在内容:

@hasSection('navigation')
   
 @yield('navigation')   
    
            
 @endif

Switch 指令

可以使用  @switch@case@break@default@endswitch 指令构造 switch 语句:

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

循环

除了分支语句,Blade 还提供了与 PHP 的循环结构相同的简化指令。这些指令的功能也与相应的 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

    {tip} 循环中可以使用 循环变量 获取循环的可评估信息,比如现在是处于循环的第一次迭代还是最后一次迭代中:

    在循环中,还可以终结循环或路过本次迭代:

    @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 变量。该变量提供了用于访问诸如当前循环的索引、当前是否为第一次或最后一次循环之类的少数有用的信息的途径:

    @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

    在嵌套循环中,可以借助 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嵌套循环中,父循环的循环变量

    注释

    Blade 也允许在视图中定义注释。不过与 HTML 注释不同,Blade 注释不会包含在返回给应用的 HTML 中:

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

    PHP

    某些情况下,在视图中嵌入 PHP 代码很有用。可以在模板中使用  @php 指令执行原生的 PHP 代码块:

    @php    //@endphp

    {tip} 尽管 Blade 提供了这个特性,但频繁使用意味着模板中嵌入了过多的逻辑。

    表单

    CSRF 域

    只要在应用中定义了 HTML 表单,就一定要在表单中包含隐藏的 CSRF 令牌域,这样一来 CSRF 保护 中间件就能校验请求。可以使用 Blade 的 @csrf 指令生成令牌域:

    
        @csrf   
        ...
    

    Method 域

    HTML 表单不能发出 PUTPATCHDELETE 请求,需要加入隐藏的 _method 域来模仿这些 HTTP 动词。Blade 的 @method 指令能够帮你创建这个域:

    
        @method('PUT')    
        ...
    

    引入子视图

    Blade 的 @include 指令允许你从其它视图中引入 Blade 视图。父视图中所有可用的变量都将在被引入的视图中可用:

        @include('shared.errors')       
                       

    被包含的视图不仅会继承父视图的所有可用数据,还能够以数组形式向被包含的视图传递额外数据:

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

    如果传递给  @include 一个不存在的视图,Laravel 会抛出错误。想要包含一个不能确定存在与否的视图,需要使用 @includeIf 指令:

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

    想要包含一个依赖于给定布尔条件的视图,可以使用 @includeWhen 指令:

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

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

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

    {note} 应当尽量避免在 Blade 视图中使用 __DIR____FILE__ 魔术常量,因为它们将指向缓存中经过编译的视图的位置。

    给被包含的视图起别名

    如果你的 Blade 被包含视图们存储在子目录中,你可能会希望为它们起个易于访问的别名。例如,一个带有如下内容的 Blade 视图内容被存储在 resources/views/includes/input.blade.php 文件中:

    可以使用 include 方法为  includes.input 起一个叫做 input 的别名。通常,这会在 AppServiceProviderboot 方法中完成:

    use Illuminate\Support\Facades\Blade;
    Blade::include('includes.input', 'input');

    一旦被包含的视图拥有了别名,就可以像 Blade 指令一样使用别名渲染它:

    @input(['type' => 'email'])

    为集合渲染视图

    可以使用 Blade 的 @each 指令在一行中整合循环和包含:

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

    第一个参数是渲染数组或集合的每个元素的视图片段。第二个参数是希望被迭代的数组或集合,第三个参数则是将被分配给视图中当前迭代的变量名。例如,想要迭代 jobs 数组,通常会在视图片段中使用 job 变量访问每个任务。当前迭代的 key 将作为视图片段中的 key 变量。

    也可以向 @each 指令传递第四个参数。这个参数是当给定数组为空时要渲染的视图片段。

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

    {note} 借助 @each 渲染视图,无法从父视图中继承变量。如果子视图需要这些变量,就必须使用 @foreach@include 代替它。

    堆栈

    Blade 允许你将视图压入堆栈,这些视图能够在其它视图或布局中被渲染。这在子视图中指定需要的 JavaScript 库时非常有用:

    @push('scripts')  
      
      
    @endpush

    如果需要,可以多次压入堆栈。通过向  @stack 指令传递堆栈名称来完成堆栈内容的渲染:

     
       
        @stack('scripts')
     

    如果想要将内容预置在栈顶,需要使用 @prepend 指令:

    @push('scripts')
        This will be second...@endpush// 然后...
      @prepend('scripts')
        This will be first...
      @endprepend

    Service 注入

    @inject 指令可以用于自 Laravel 的 服务容器 中获取服务。传递给 @inject 的第一个参数是将要置入的服务变量名,第二个参数是希望被解析的类或接口名:

    @inject('metrics', 'App\Services\MetricsService')
    
        Monthly Revenue: {{ $metrics->monthlyRevenue() }}.

    扩展 Blade

    Blade 允许你使用 directive 方法自定义指令。当 Blade 编译器遇到自定义指令时,这会调用该指令包含的表达式提供的回调。

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

    format('m/d/Y H:i'); ?>";       
          });    
        }   
        /**
         * 在容器中注册绑定.
         *
         * @return void
         */ 
          public function register()  
            { 
                 //    
             }
          }

    如你所见,我们将在传递给该指令的任意表达式中链式调用  format 方法。在这个例子中,该指令将生成如下原生 PHP 代码:

    format('m/d/Y H:i'); ?>

    {note} 在更新 Blade 指令的逻辑之后,需要 Blade 视图的所有缓存。可以使用  view:clear Artisan 命令删除 Blade 视图缓存。

    自定义 If 语句

    在定义简单的、自定义条件语句时,编写自定义指令比必须的步骤复杂。在这种情况下,Blade 提供了 Blade::if 方法,它允许你使用闭包快速度定义条件指令。例如,定义一个校验当前应用环境的自定义指令,可以在  AppServiceProviderboot 方法中这样做:

    use Illuminate\Support\Facades\Blade;
    /**
     * 执行注册后引导服务
     *
     * @return void
     */
     public function boot(){  
       Blade::if('env', function ($environment) {     
       return app()->environment($environment);   
       });
     }

    一旦定义了自定义条件指令,就可以在模板中轻松的使用:

    @env('local')    
      // 应用在本地环境中运行...
    @elseenv('testing')    
      // 应用在测试环境中运行...
    @else    
      // 应用没有在本地和测试环境中运行...
    @endenv
    本文章首发在 LearnKu.com 网站上。

    本地化

    相关

    视频

    RELATED VIDEOS

    更多

    免费

    php8,我来也
    初级 php8,我来也

    315072次学习

    收藏

    免费

    Thinkphp6.0正式版视频教程

    免费

    细说PHP第一季
    中级 细说PHP第一季

    265134次学习

    收藏

    免费

    简单聊聊PHP创业那点事
    初级 简单聊聊PHP创业那点事

    12919次学习

    收藏

    科技资讯

    更多

    精选课程

    更多
    前端入门_HTML5
    前端入门_HTML5

    共29课时

    61.7万人学习

    CSS视频教程-玉女心经版
    CSS视频教程-玉女心经版

    共25课时

    39.3万人学习

    JavaScript极速入门_玉女心经系列
    JavaScript极速入门_玉女心经系列

    共43课时

    70.9万人学习

    独孤九贱(1)_HTML5视频教程
    独孤九贱(1)_HTML5视频教程

    共25课时

    61.6万人学习

    独孤九贱(2)_CSS视频教程
    独孤九贱(2)_CSS视频教程

    共22课时

    23万人学习

    独孤九贱(3)_JavaScript视频教程
    独孤九贱(3)_JavaScript视频教程

    共28课时

    33.9万人学习

    独孤九贱(4)_PHP视频教程
    独孤九贱(4)_PHP视频教程

    共89课时

    125万人学习

    热门下载

    更多
    关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
    php中文网:公益在线php培训,帮助PHP学习者快速成长!
    关注服务号 技术交流群
    PHP中文网订阅号
    每天精选资源文章推送
    PHP中文网APP
    随时随地碎片化学习

    Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号