第四章 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(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 视图的全部内容,欲知更多内容,请听下章详解。
网友评论