Laravel 视图

第四章 Laravel 视图

  • 视图定义
  • 视图标签
  • blade模板布局
  • 数据处理
  • 加载静态资源

4.1 创建视图:

4.1.1 视图定义:

视图包含应用程序的 HTML,并且将控制器 / 应用程序逻辑与演示逻辑分开。视图文件存放于 resources/views 目录下。一个简单的视图如下所示:

<!-- 此视图文件位置 resources/views/greeting.blade.php -->
<html>
    <body>
        <h1>Hello, {{ $name }}</h1>
    </body>
</html>

该视图文件位于 resources/views/greeting.blade.php, 可以使用全局辅助函数 view 将其返回:

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

如你所见, 传递给 view 辅助函数的第一个参数对应 resources/views 目录中视图文件的名称。第二个参数是应该可供视图使用的数据数组。在这种情况下,我们传递 name变量,该变量将使用 Blade syntax 在视图中显示。

当然,视图文件也可以嵌套在 resources/views 目录的子目录中。「点」符号可以用来引用嵌套视图。例如,如果你的视图存储在 resources/views/admin/profile.blade.php,则可以这样引用它:

return view('admin.profile', $data);

判断视图文件是否存在:

如果需要判断视图文件是否存在,可以使用 View facade。如果存在,exists 方法会返回 true

use Illuminate\Support\Facades\View;

if (View::exists('emails.customer')) {
    //
}

向视图传递参数:

正如您在前面的示例中所看到的,您可以将一组数据传递给视图:

return view('greetings', ['name' => 'Victoria']);

与所有视图共享数据:

有时候,你可能需要共享一段数据给应用程序的所有视图。 你可以在服务提供器的 boot方法中调用视图 Facade 的 share 方法。例如,可以将它们添加到 AppServiceProvider 或者为它们生成一个单独的服务提供器:

<?php

namespace App\Providers;

use Illuminate\Support\Facades\View;

class AppServiceProvider extends ServiceProvider
{
    /**
     * 注册任何应用服务
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * 引导任何应用程序服务
     *
     * @return void
     */
    public function boot()
    {
        View::share('key', 'value');
    }
}

4.2 模板:

4.2.1 模板标签:

除了模板继承和显示数据之外,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

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

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

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

身份验证指令

@auth@guest 指令可用于快速确定当前用户是否经过身份验证或是 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

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

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

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

@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
4.2.2 模板布局:

定义布局

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

<!-- 保存在 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 指令是用来显示指定部分的内容。

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

指令:

  • @section:指令定义视图的一部分内容

  • @show:@section指令下面的结束符合。还有其他结束符@stop、@overwrite 以及 @append 来结束、@endsection

  • @show: 指的是执行到此处时将该 section 中的内容输出到页面

    • @stop 则只是进行内容解析,并且不再处理当前模板中后续对该section的处理。并不输出内容到页面
    • @overwrite:覆盖之前的所有定义,以这次的为准
    • @append:再次添加模板
  • @yield:用来显示值定部分内容。如果你要定义的部分没有默认内容让子模板扩展的,那么用 @yield(name,default) 的形式会比较方便

  • @parent:保留父模板内容。但是 @yield 模板继承后继承模板将不会保留父模板内容

  • 注释部分也很简单,就是将 {{-- …--}} 替换成 <?php /* … */ ?php>
    compileRawEchos -> 输出未经转义的内容 ({!! ... !!})
    compileEscapedEchos -> 输出转义之后的内容 ({{{ ... }}})
    compileRegularEchos -> 正常输出 ({{ ... }})

Blade模板执行流程:
在使用 View 组件输出时,不管是调用 helpers 中提供的 view 函数还是使用 Facades 提供静态接口 View::make(),实际上执行的都是 Illuminate\View\Factory 中的 make方法。以此为入口,很容易就能知道视图解析输出的流程:
1、查找视图文件;
2、根据文件名后缀从 Container 中取出响应的引擎;
3、加载视图文件或编译后加载编译后的文件执行,同时将需要解析的数据暴露在视图文件环境中。
Factory 中的一些方法完成了以上第一步的过程,文件查找是调用的 FileViewFinder,其中使用了一些 Illuminate\Filesystem\Filesystem 中的方法,这个类中还有一些方法是跟 events 相关的,这里就忽略不表了。

在以上步骤中,如果中获取到的视图文件是需要“编译”的,引擎会调用 “Blade 编译器”将原视图进行“编译”并保存在 cache 目录中然后加载输出。下次调用时如果发现源文件并没有被修改过就不再重新编译而是直接获取缓存文件并输出。

编译:“编译”两个字加引号,因为这显然不是真正意义上的代码编译的过程,只是一些正则替换语法的过程。

  • {{ 与 }} 之间是要输出的内容,也有扩展的两个方法 {{{ ... }}} 和 {!! .. !!} 分别用于转义输出和不转义输出,5.0 以后的版本中 {{ ... }} 之间的默认情况下也是转义输出的;

  • @ 符号开头的都是指令,包括 PHP 本身有的 if else foreach 以及扩展的 include yield stop 等等;

  • 而 Blade 对于解析的处理实际上是分了四种情况:

    • Extensions -> 扩展部分
    • Statements -> 语句块(就是 @ 开头的指令)
    • Comments -> 注释部分({{-- ... --}} 的写法,解析之后是 PHP 的注释而不是 HTML的注释)
    • Echos -> 输出

在解析(解析是在 cache 不存在的情况下)过程中,Blade 会先使用 token_get_all 函数获取到视图文件中的被 PHP 解释器认为是 HTML(T_INLINE_HTML)的部分,然后依次进行以上四种情况的解析。

扩展布局

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

<!-- 保存在 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 指令向布局的 sidebar 追加(而非覆盖)内容。 在渲染视图时,@parent 指令将被布局中的内容替换。

@yield 指令还接受一个默认值作为第二个参数。如果被 「yield」的片段未定义,则该默认值被渲染:

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

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

Route::get('blade', function () {
    return view('child');
});
4.2.3 组件 & 插槽

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

注:插槽定义好,组件必须要实现其内容

<!-- /resources/views/alert.blade.php -->

<div class="alert alert-danger">
    {{ $slot }}
</div>

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

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

若要指示 Laravel 从组件的给定数组中加载存在的第一个视图,可以使用 componentFirst 指令:

@componentFirst(['custom.alert', 'alert'])
    <strong>Whoops!</strong> Something went wrong!
@endcomponent

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

<!-- /resources/views/alert.blade.php -->

<div class="alert alert-danger">
    <div class="alert-title">{{ $title }}</div>

    {{ $slot }}
</div>

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

@component('alert')
    @slot('title')
        Forbidden
    @endslot

    You are not allowed to access this resource!
@endcomponent
4.3 加载静态资源

采用函数
asset();//直接定位到public下面
publi_path()

各位同学以上就是 Laravel 视图的全部内容,欲知更多内容,请听下章详解。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容