美文网首页
Laravel 文档阅读:Blade 模板

Laravel 文档阅读:Blade 模板

作者: 晨曦入诗 | 来源:发表于2018-10-14 21:38 被阅读88次

    简介


    Blade 是 Laravel 提供的模板引擎,它简单强大。不像其他的 PHP 模板引擎,Blade 允许在视图中使用原生 PHP 代码。实际上,所有的 Blade 视图最终都会被编译成原生 PHP 代码,缓存在 storage/framework/views 文件夹中。Laravel 使用的是这些编译后的缓存文件,而不是视图本身,所以,Blade 对于应用程序来说是零开销的。当你修改了视图文件,那么它会重新编译并缓存,以便使用。Blade 视图以 blade.php 为后缀名,一般存放于 resources/views 文件夹中。

    模板继承


    定义布局文件

    Blade 模板引擎的主要两个优点是 “模板继承” 和 “区块”。举一个简单的例子,一个项目里,几乎所有的页面都是一样的布局,这时候就可以把这个布局提炼出来,作为母版页,继承了这个母版页的的页面都有一样的布局效果,成为母版页的子页。母版页还叫布局文件,布局文件就是一个 Blade 视图:

    <!-- Stored in resources/views/layouts/app.blade.php -->
    <html>
           <head>
                 <title>App Name - @yield('title')</title>
           </head>
           <body>
             @section('sidebar')
                   This is the master sidebar.
             @show
             <div class="container">
                  @yield('content')
             </div>
           <body>
    </html>
    

    布局文件里除了基础的 HTNL 标签,还使用了两个指令:@section@yield@section定义区块,@yield 定义区块里的内容。
    下面。来定义布局文件的子页。

    继承布局文件

    子页中,使用 Blade 的 @extends 指令指定 “继承” 的布局文件,使用 @section 指令为在布局文件中使用 @section@yield 指令的地方注入内容:

    <!-- Stored in resources/views/child.blade.php -->
    
    @extends('layouts.app')
    @section('title','Page Title')
    
    @section('sidebar')
           <p> This is appended to the master sideebar</p>
    @endsection
    
    @section('content')
             <p>This ismy body content. </p>
    @endsection
    

    可以看到,在布局文件中使用 @yield 指令的地方,在子页中仍然使用 @section 注入内容;在布局文件中使用 @section 指令定义的一个好处是:在子页中使用 @section 注入时,可以使用 @parent 指令附加(而非重写)在布局文件中的内容,而在布局文件中使用 @yield 指令定义的地方是做不到的。@parent 指令会在视图渲染的时替换成布局文件里的内容。
    注意,与在文件布局里定义的 sidebar 不同的是,子页里使用 @endsection 结束,而非 @show 。因为 @endsection 仅用来定义区块,而 @show 是用来定义、立马产出区块的。
    从路由中直接返回视图文件,要用到全局辅助函数 helper :

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

    组件&插槽


    组件和插槽提供了类似布局和区块的优点。而组件和插槽的心智模型更符合直觉。设想一下,在我们的项目中有一个可重复的 “弹框” 组件:

    <!-- Stored resource/views/alter.blade.php -->
    <div class="alter alter-danger">
           {{ $slot }}
    </div>
    

    {{ $slot }} 表示插入组建的内容。构建此组件,是使用 Blade 的@component指令:

    @component('alter')
            <strong>Whoops!</strong> Something went wrong!
    @endcomponent
    

    在这个场景里,{{ $slot }} 变量的内容是:

    <strong>Whoops! </strong> Something went wrong!
    

    有时一个组件需要多个插槽。这时,只需要稍改组件代码,定义一个 “标题” 插槽,这个插槽称命名插槽。命名插槽是通过简单的 “打印” 匹配其名称的变量来显示内容的:

    <!-- Stored resources/views/alter.blade.php-->
    
    <div class="alter alter-danger">
             <div class="alter-title">{{ $title }}</div>
                {{ $slot }}
    </div>
    

    为名名插槽注入内容,使用 @slot 指令。所有不在 @slot 指令里的内容都会传递给组件里的 $slot 变量。

    @compontent ('alter')
             @slot('title')
                Forbidden
             @endslot
         You are not allowed to access this resource!
    @edcompontent~ 
    

    为组建传递额外数据:

    有时需要为组建件递额外数据。为此,可以为 @conponent 指令传递第二个数组参数。指定要传递的额外。据所有过去的额外数据作为变量,在组件模板里都可以取的:

    @component
         <compontent('alter', ['foo' => 'bar');
             .....
    @endCompontent 
    

    显示数据

    向 Blade 视图传递数据,是通过将变量包裹在 [ ] 里实现的:

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

    下面就可以使用 name 变量显示内容了:

    Hello! {{ $name }}
    

    {{ }} 是 Blade 视图的打印语句,当然,打印语句里不限制只能打印变量内容,也可以使用 PHP 函数。实际上,打印语句这里可以使用任何 PHP 代码:

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

    显示非转移数据

    默认,所有传递给 Blade {{ }} 语句的内容都会使用 htmlspecialchar 函数处理、将内容转义,避免 XSS 攻击。如果无需转义输出的内容,可以使用下面语法:

    Hello! {{!! $name !!}}.
    

    不过千万要小心,应该优先选择使用转义的 {{ }} 语法避免 XXS 攻击。因为,有时你很难避免用户有意的、无意的数据输入。

    Blade & JavaScript 框架

    由于一些 JavaScript 框架也使用花括号 {{ }} 语法解析内容,为了区分开 Blade 和这些用到的 JavaScript 框架,你可以使用 @ 符号来告诉 Blade 模板引擎说,这个地方不要动,保持原样就可以了:

    <h1>Laravel</h1>
    
    Hello! @{{ $name }}
    

    上面例子里, @ 符号会从 Blade 中删除,而 {{ $name }} 会保持原样,用来给你的 JavaScript 框架渲染使用。

    @verbatim 指令

    如果使用 JavaScript 框架渲染的模块区域很大,这时就可以使用 @verbatim 指令包裹这些模板区域,这样就避免了在每个Blade 打印语句前都跟上 @ 符号的麻烦:

    @verbatim
          <div class="container">
             Hello! {{ $name }}
          </div>
    @endverbatim
    

    控制结构

    除了模板继承和显示数据,Blade 还未常见的 PHP 结构提供了快捷方式,比如条件谈判和循环。这些快捷方式提供了一种非常干净、简洁的控制结构,并且保持了原生 PHP 的形式。

    if 语句

    构造 if 语句使用 @if@elseif 、@else 和 endif 指令。这些指令和原生 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.
    @endless
    

    除了讨论过的条件判断指令,Blade 还提供了 @isset@empty 指令,都与在原生 PHP 里的对应功能相同:

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

    认证

    @auth@guest 指令用来判断当前用户是认证用户还是游客:

    @auth
            // The user is authenticated...
    @endauth
    
    @guest
          //  The useris 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)
        <p>This is user {{ $user->id }} </p>
    @endforeach
    
    @forelse($users as $user)
        <li> {{ $user->name }}</li>
    @empty
        <p>No user </p>
    @endforelse
    
    @while(true)
        <p>I'm looping forever.</p>
    @endwhile
    

    在循环时可以结束或跳出当前的迭代:

    @foreach($users as $user)
       @if ($user->type == 1)
            @continue
       @endif
    
       <li>{{ $user->name }}</li>
     
       @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
    
       <p>This is user {{ $user->id }}</p>
    @endforeach
    

    如果是在嵌套的循环里,就可以使用 $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 变量提供的有用属性列举如下:

    image.png

    注释

    Blade 的注释语法是 {{-- --}} 。不像 HTML 注释,Blade 模板注释不会出现在最终渲染的 HTML 代码里:

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

    PHP

    Blade 允许在一个视图里通过 @include 指令引入一个视图。使用 @include 指令的视图称为父级视图,引入的视图称为子视图。父级视图的所有变量在子视图里都是可以获得的:

    <div>
       @include('shared.error')
        <form>
             <!-- Form Contents -->
        </form>
    </div>
    

    虽然子视图会继承父级视图内的所有变量,但是你也可以为引入的子视图传递额外数据,这些数据是以数组的形式传递过去的:

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

    当你用 @include 引入的视图不存在时, Laravel 会抛出错误。如果引入的试图不确定是否存在,应该使用 @includeIf 指令:

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

    如果要通过一个布尔值判断是否引入子视图,需要使用 @includeWhen 指令:

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

    注意:不要使用 __DIR____FILE__ 常量引入 Blade 视图,因为程序实际使用的是编译后的、缓存在 storage/framework/views 文件夹中的文件。

    为集合渲染视图

    @each 指令整合了循环数据和引入视图的功能:

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

    第一个参数是为数组或者集合中每个元素渲染数据时指定的视图,第二个参数是要便利的数组或集合,第三个参数是当前迭代的元素数据在子视图中的变量名。在上面的例子里,我们遍历的数组是 jobs , 在 view.name 视图里渲染 job 变量,当前迭代的 key 使用 key 变量获取。
    也可以为 @each 指令传递第四个参数,这是在给定数组元素为空时渲染的视图:

    @each($bollean, 'view.name', [ 'some' => 'data'], 'view.empty')
    

    注意:使用 @each 渲染的视图不从父级模板里继承变量。如果子视图还需要这些变量,你应该使用 foreach@include 指令组合。

    堆栈


    Blade 允许你使用 @push 指令向命名堆栈里推入内容,命令堆栈以 @stack 指令定义,可以定义在普通视图或者布局文件里,推入的内容会在视图或者布局文件里渲染出来。这在为子视图添加额外的 JavaScript 库的场景下特别有用。

    <!-- 在视图或者布局文件里定义堆栈 -->
    <head>
        <!-- Head Contents -->
        @stack('scripts')
    </head>
    
    <!-- 在子视图中推入堆栈内容 -->
    @push('scripts')
        <script src="/example.js"></script>
    @endpush
    

    你可以尽你自己所需的多次向堆栈推入数据。

    服务注入


    @inject 指令可以从 Laravel 的服务提供者中获得服务。传递给 @inject 指令的第一个参数是一个变量名,获得的服务就是存放在这个变量里,第二个参数就是你要解析的服务的类名或接口名。

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

    扩展 Blade


    Blade 允许你使用 directive 方法创建自定义指令。当 Blade 方法遇到自定义指令时,会将接收到的表达式 (expression)放在自定义指令的回调闭包里处理。
    在下面的例子里,我们创建了一个 @datatime($var) 指令,$var应该是一个DateTime 实例:

    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 "<?php echo ($expression->format('m/d/Y H:i'); ?>)";
             });
         }
        /**
         * Register bindings in the container.
         *
         * @return void
         */
         public function register()
         {
              //
         }
    }
    

    可以看到,我们在传过来的表达式上使用了 format 方法。在这个例子里,@datetime($var) 指令最终生成的 PHP 代码如下:

    <?php echo ($var)->format('m/d/Y H:i'); ?>
    

    注意:在更新自定义指令后,需要删除所有的视图文件,可以用 view:cache Artisan 命令实现。

    自定义 if 语句

    当自定义涉及简单的条件判断时,使用 Blade::directive 的方式可能会变得稍复杂些。为此, Blade 引入了 Blade::if 方法使用闭包来快速自定义条件判断指令。例如,我们定义一个指令,判断当前的项目环境,可以选择在 AppServiceProviderboot 里做这件事情:

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

    定义好后,咱使用它:

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

    是不是很简单呢 ??

    相关文章

      网友评论

          本文标题:Laravel 文档阅读:Blade 模板

          本文链接:https://www.haomeiwen.com/subject/xdhaaftx.html