Laravel Blade 模板

简介

Blade是Laravel提供的简单但功能强大的模板引擎。与其他流行的PHP模板引擎不同,Blade不会限制我们在视图中使用纯PHP代码。实际上,所有Blade视图都被编译为纯PHP代码并被缓存起来。blade视图文件使用.blade.php文件扩展名,并且通常存储在resources/views目录中。


模板继承

定义布局

使用Blade的两个主要好处是模板继承和section。首先,让我们看一个简单的例子。我们将检查“主”页面的布局。由于大多数Web应用程序在各个页面上都保持相同的总体布局,因此将这种布局定义为单个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>

如您所见,该文件包含典型的HTML标记。但是,请注意@section@yield指令。@section 顾名思义,该指令定义了内容的一部分,而 @yield 伪指令用于显示给定部分的内容。

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

扩展布局

定义子视图时,请使用Blade @extends指令指定子视图应“继承”的布局。扩展Blade布局的视图可以使用@section指令将内容注入到布局的各节中。请记住,如上例所示,这些部分的内容将在布局中使用@yield引用显示:

<!-- Stored in resources/views/child.blade.php -->

@extends('layouts.app')

@section('title', 'Page Title')

@section('sidebar')
    @parent

    <p>This is appended to the master sidebar.</p>
@endsection

@section('content')
    <p>This is my body content.</p>
@endsection

在此示例中,sidebar部分利用@parent指令将内容附加(而不是覆盖)到布局的侧边栏。@parent呈现视图时,该指令将被布局的内容替换,也就是说@parent相当于一个占位符。

与前面的示例相反,sidebar部分以@endsection结束,而不是使用@show。@endsection指令将只定义一个内容块,而@show不仅仅是定义内容块,而是在定义之后立即引用该部分。

@yield指令还有第二个参数,这个参数指定一个默认值。如果产生的部分未定义,则将呈现此值:

@yield('content', View::make('view.name'))

blade 视图可以使用全局view帮助函数从路由中直接返回:

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

显示数据

我们可以通过在变量外面加上花括号,使得该变量可以在视图中显示。例如,给定以下路由:

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

我们可以这样显示name变量的内容:

Hello, {{ $name }}.

Blade {{ }}语句通过PHP的htmlspecialchars功能自动发送,以防止XSS攻击。

不仅限于显示传递给视图的变量的内容。也可以在视图中调用任何的PHP函数,并显示函数的返回值。实际上,可以将所需的任何PHP代码放入Blade echo语句中:

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

显示未转义的数据

默认情况下,Blade {{ }}语句通过PHP的htmlspecialchars功能自动发送,以防止XSS攻击。如果您不希望对数据进行转义,则可以使用以下语法:

Hello, {!! $name !!}.

显示用户提供的内容时,要格外小心。在显示用户提供的数据时,建议始终使用转义的双花括号语法来防止XSS攻击。

渲染JSON

有时,可能会将数组传递给视图。然后将其呈现为JSON,以便初始化JavaScript变量。例如:

<script>
    var app = <?php echo json_encode($array); ?>;
</script>

可以使用@json指令代替json_encode。@json指令接受与PHP json_encode函数相同的参数:

<script>
    var app = @json($array);

    var app = @json($array, JSON_PRETTY_PRINT);
</script>

我们应该使用@json指令将现有变量呈现为JSON。Blade模板基于正则表达式,尝试将复杂的表达式传递给指令可能会导致意外失败。

HTML实体编码

默认情况下,Blade(和Laravel 的e函数)将对HTML实体进行双重编码。如果要禁用双重编码,请从AppServiceProviderboot方法中调用Blade::withoutDoubleEncoding方法:

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Blade::withoutDoubleEncoding();
    }
}

Blade 和 JavaScript 框架

由于许多JavaScript框架还使用“大括号”来指示应在浏览器中显示给定的表达式,因此可以使用@符号来通知Blade渲染引擎其后面的表达式应保持不变。例如:

<h1>Laravel</h1>

Hello, @{{ name }}.

在此示例中,@符号将被Blade删除;但是,{{ name }}Blade引擎不会去处理,这样就可以使JavaScript框架来处理了。

@符号还可用于转义Blade指令:

{{-- Blade --}}
@@json()

<!-- HTML output -->
@json()

@verbatim 指令

如果要在模板的很大一部分中显示JavaScript变量,则可以将HTML包装在@verbatim指令中,这样就不必在每个Blade echo语句前添加@符号前缀:

@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.
@endunless

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

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

@empty($records)
    // $records is "empty"...
@endempty

认证指令

@auth@guest指令可被用于快速确定当前用户是否被认证:

@auth
    // The user is authenticated...
@endauth

@guest
    // The user is not authenticated...
@endguest

如果需要,我们可以在使用@auth@guest指令时指定应检查的身份验证保护:

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

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

section 指令

可以使用@hasSection指令检查某个section是否包含内容:

@hasSection('navigation')
    <div class="pull-right">
        @yield('navigation')
    </div>

    <div class="clearfix"></div>
@endif

我们可以使用sectionMissing指令来确定某个section是否不包含内容:

@sectionMissing('navigation')
    <div class="pull-right">
        @include('default-navigation')
    </div>
@endif

Environment 指令

我们可以使用@production指令检查应用程序是否在生产环境中运行:

@production
    // Production specific content...
@endproduction

或者,可以使用@env指令确定应用程序是否在特定环境中运行:

@env('staging')
    // The application is running in "staging"...
@endenv

@env(['staging', 'production'])
    // The application is running in "staging" or "production"...
@endenv

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循环结构的简单指令。同样,这些指令中的每个指令的功能都与它们的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 users</p>
@endforelse

@while (true)
    <p>I'm looping forever.</p>
@endwhile

循环时,我们可以使用loop变量来获取有关循环的信息,例如我们是否处于循环的第一次还是最后一次迭代中。

使用循环时,我们也可以结束循环或跳过当前循环:

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

    <li>{{ $user->name }}</li>

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

还可以在指令声明的一行中包含条件语句:

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

    <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属性访问父循环的变量:

@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->even 这是否是循环中的均匀迭代。
$loop->odd 这是否是循环中的奇数次迭代。
$loop->depth 当前循环的嵌套级别。
$loop->parent 在嵌套循环中,父级的循环变量。

注释

Blade还允许我们在视图使用注释。但是,与HTML注释不同,Blade注释不包含在应用程序返回的HTML中:

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

PHP

在某些情况下,将PHP代码嵌入视图中是不可避免的。可以使用Blade的@php指令在模板中执行一个纯PHP代码块:

@php
    //
@endphp

尽管Blade提供了此功能,但频繁使用它可能表明您模板中嵌入了太多逻辑。可能需要优化我们的代码了

@once指令

@once指令允许我们定义模板的一部分,每次渲染周期仅执行一次。这对于使用stack将给定的JavaScript片段推入页面的header可能很有用。例如,如果要在循环中渲染给定的组件,则可能希望仅在首次渲染该组件时将JavaScript放入header:

@once
    @push('scripts')
        <script>
            // Your custom JavaScript...
        </script>
    @endpush
@endonce

查看笔记

扫码一下
查看教程更方便