第四章 Laravel 視圖
- 視圖定義
- 視圖標(biāo)簽
- blade模板布局
- 數(shù)據(jù)處理
- 加載靜態(tài)資源
4.1 創(chuàng)建視圖:
4.1.1 視圖定義:
視圖包含應(yīng)用程序的 HTML,并且將控制器 / 應(yīng)用程序邏輯與演示邏輯分開。視圖文件存放于 resources/views
目錄下。一個(gè)簡(jiǎn)單的視圖如下所示:
<!-- 此視圖文件位置 resources/views/greeting.blade.php -->
<html>
<body>
<h1>Hello, {{ $name }}</h1>
</body>
</html>
該視圖文件位于 resources/views/greeting.blade.php
, 可以使用全局輔助函數(shù) view
將其返回:
Route::get('/', function () {
return view('greeting', ['name' => 'James']);
});
如你所見, 傳遞給 view
輔助函數(shù)的第一個(gè)參數(shù)對(duì)應(yīng) resources/views
目錄中視圖文件的名稱。第二個(gè)參數(shù)是應(yīng)該可供視圖使用的數(shù)據(jù)數(shù)組。在這種情況下,我們傳遞 name
變量,該變量將使用 Blade syntax 在視圖中顯示。
當(dāng)然,視圖文件也可以嵌套在 resources/views
目錄的子目錄中?!更c(diǎn)」符號(hào)可以用來引用嵌套視圖。例如,如果你的視圖存儲(chǔ)在 resources/views/admin/profile.blade.php
,則可以這樣引用它:
return view('admin.profile', $data);
判斷視圖文件是否存在:
如果需要判斷視圖文件是否存在,可以使用 View
facade。如果存在,exists
方法會(huì)返回 true
:
use Illuminate\Support\Facades\View;
if (View::exists('emails.customer')) {
//
}
向視圖傳遞參數(shù):
正如您在前面的示例中所看到的,您可以將一組數(shù)據(jù)傳遞給視圖:
return view('greetings', ['name' => 'Victoria']);
與所有視圖共享數(shù)據(jù):
有時(shí)候,你可能需要共享一段數(shù)據(jù)給應(yīng)用程序的所有視圖。 你可以在服務(wù)提供器的 boot
方法中調(diào)用視圖 Facade 的 share
方法。例如,可以將它們添加到 AppServiceProvider
或者為它們生成一個(gè)單獨(dú)的服務(wù)提供器:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\View;
class AppServiceProvider extends ServiceProvider
{
/**
* 注冊(cè)任何應(yīng)用服務(wù)
*
* @return void
*/
public function register()
{
//
}
/**
* 引導(dǎo)任何應(yīng)用程序服務(wù)
*
* @return void
*/
public function boot()
{
View::share('key', 'value');
}
}
4.2 模板:
4.2.1 模板標(biāo)簽:
除了模板繼承和顯示數(shù)據(jù)之外,Blade 還為常見的 PHP 控制結(jié)構(gòu)提供了便捷的快捷方式,例如條件和循環(huán)語句。這些快捷方式提供了一種簡(jiǎn)潔的處理 PHP 控制語句的方法,同時(shí)保持了與 PHP 中的相應(yīng)結(jié)構(gòu)的相似性。
IF 語句
你可以使用 @if
、@elseif
、@else
和 @endif
指令來構(gòu)造 if
語句。這些指令的功能與它們?cè)?PHP 中對(duì)應(yīng)的語句功能相同:
@if (count($records) === 1)
I have one record!
@elseif (count($records) > 1)
I have multiple records!
@else
I don't have any records!
@endif
除了已經(jīng)討論過的條件指令之外, @isset
和 @empty
指令還可以用作各自 PHP 函數(shù)的快捷方式:
@isset($records)
// $records is defined and is not null...
@endisset
@empty($records)
// $records is "empty"...
@endempty
身份驗(yàn)證指令
@auth
和 @guest
指令可用于快速確定當(dāng)前用戶是否經(jīng)過身份驗(yàn)證或是 guest:
@auth
// The user is authenticated...
@endauth
@guest
// The user is not authenticated...
@endguest
如果需要,可以在使用 @auth
和 @guest
指令時(shí)指定應(yīng)被校驗(yàn)的 身份驗(yàn)證 :
@auth('admin')
// The user is authenticated...
@endauth
@guest('admin')
// The user is not authenticated...
@endguest
switch 語句
Switch 語句可以使用 @switch
, @case
, @break
, @default
和 @endswitch
指令來構(gòu)造:
@switch($i)
@case(1)
First case...
@break
@case(2)
Second case...
@break
@default
Default case...
@endswitch
循環(huán)
除了條件語句之外,Blade 還提供了使用 PHP 循環(huán)結(jié)構(gòu)的簡(jiǎn)單指令。同樣,這些指令的每個(gè)函數(shù)都與它們相對(duì)于的 PHP 函數(shù)相同:
@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
使用循環(huán)時(shí),也可以結(jié)束循環(huán)或跳過當(dāng)前迭代:
@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
循環(huán)變量
循環(huán)過程中,在循環(huán)體內(nèi)有一個(gè)可用的 $loop
變量。該變量提供了用于訪問諸如當(dāng)前循環(huán)的索引、當(dāng)前是否為第一次或最后一次循環(huán)之類的少數(shù)有用的信息的途徑:
@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 的兩個(gè)主要優(yōu)點(diǎn)是 模板繼承
和區(qū)塊
。為方便入門,讓我們先通過一個(gè)簡(jiǎn)單的例子來上手。首先,我們來研究一個(gè)「主」頁面布局。因?yàn)榇蠖鄶?shù) web 應(yīng)用會(huì)在不同的頁面中使用相同的布局方式,因此可以很方便地定義單個(gè) 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 語法。不過,請(qǐng)注意 @section
和 @yield
指令。 @section
指令定義了視圖的一部分內(nèi)容,而 @yield
指令是用來顯示指定部分的內(nèi)容。
現(xiàn)在,我們已經(jīng)定義好了這個(gè)應(yīng)用程序的布局,接下來,我們定義一個(gè)繼承此布局的子頁面。
指令:
@section
:指令定義視圖的一部分內(nèi)容@show
:@section指令下面的結(jié)束符合。還有其他結(jié)束符@stop、@overwrite 以及 @append 來結(jié)束、@endsection-
@show
: 指的是執(zhí)行到此處時(shí)將該 section 中的內(nèi)容輸出到頁面- @stop 則只是進(jìn)行內(nèi)容解析,并且不再處理當(dāng)前模板中后續(xù)對(duì)該section的處理。并不輸出內(nèi)容到頁面
-
@overwrite
:覆蓋之前的所有定義,以這次的為準(zhǔn) -
@append
:再次添加模板
@yield
:用來顯示值定部分內(nèi)容。如果你要定義的部分沒有默認(rèn)內(nèi)容讓子模板擴(kuò)展的,那么用 @yield(default) 的形式會(huì)比較方便
@parent
:保留父模板內(nèi)容。但是@yield
模板繼承后繼承模板將不會(huì)保留父模板內(nèi)容注釋部分也很簡(jiǎn)單,就是將 {{-- …--}} 替換成 <?php /* … */ ?php>
compileRawEchos -> 輸出未經(jīng)轉(zhuǎn)義的內(nèi)容 ({!! ... !!})
compileEscapedEchos -> 輸出轉(zhuǎn)義之后的內(nèi)容 ({{{ ... }}})
compileRegularEchos -> 正常輸出 ({{ ... }})
Blade模板執(zhí)行流程:
在使用 View 組件輸出時(shí),不管是調(diào)用 helpers 中提供的 view 函數(shù)還是使用 Facades 提供靜態(tài)接口 View::make(),實(shí)際上執(zhí)行的都是 Illuminate\View\Factory 中的 make
方法。以此為入口,很容易就能知道視圖解析輸出的流程:
1、查找視圖文件;
2、根據(jù)文件名后綴從 Container 中取出響應(yīng)的引擎;
3、加載視圖文件或編譯后加載編譯后的文件執(zhí)行,同時(shí)將需要解析的數(shù)據(jù)暴露在視圖文件環(huán)境中。
Factory 中的一些方法完成了以上第一步的過程,文件查找是調(diào)用的 FileViewFinder,其中使用了一些 Illuminate\Filesystem\Filesystem 中的方法,這個(gè)類中還有一些方法是跟 events 相關(guān)的,這里就忽略不表了。
在以上步驟中,如果中獲取到的視圖文件是需要“編譯”的,引擎會(huì)調(diào)用 “Blade 編譯器”將原視圖進(jìn)行“編譯”并保存在 cache 目錄中然后加載輸出。下次調(diào)用時(shí)如果發(fā)現(xiàn)源文件并沒有被修改過就不再重新編譯而是直接獲取緩存文件并輸出。
編譯:“編譯”兩個(gè)字加引號(hào),因?yàn)檫@顯然不是真正意義上的代碼編譯的過程,只是一些正則替換語法的過程。
{{ 與 }} 之間是要輸出的內(nèi)容,也有擴(kuò)展的兩個(gè)方法 {{{ ... }}} 和 {!! .. !!} 分別用于轉(zhuǎn)義輸出和不轉(zhuǎn)義輸出,5.0 以后的版本中 {{ ... }} 之間的默認(rèn)情況下也是轉(zhuǎn)義輸出的;
@ 符號(hào)開頭的都是指令,包括 PHP 本身有的 if else foreach 以及擴(kuò)展的 include yield stop 等等;
-
而 Blade 對(duì)于解析的處理實(shí)際上是分了四種情況:
- Extensions -> 擴(kuò)展部分
- Statements -> 語句塊(就是 @ 開頭的指令)
- Comments -> 注釋部分({{-- ... --}} 的寫法,解析之后是 PHP 的注釋而不是 HTML的注釋)
- Echos -> 輸出
在解析(解析是在 cache 不存在的情況下)過程中,Blade 會(huì)先使用 token_get_all 函數(shù)獲取到視圖文件中的被 PHP 解釋器認(rèn)為是 HTML(T_INLINE_HTML)的部分,然后依次進(jìn)行以上四種情況的解析。
擴(kuò)展布局
在定義一個(gè)子視圖時(shí),使用 Blade 的 @extends
指令指定子視圖要「繼承」的視圖。擴(kuò)展自 Blade 布局的視圖可以使用 @section
指令向布局片段注入內(nèi)容。就如前面的示例中所示,這些片段的內(nèi)容將由布局中的 @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
在這個(gè)示例中, sidebar
片段利用 @parent
指令向布局的 sidebar 追加(而非覆蓋)內(nèi)容。 在渲染視圖時(shí),@parent
指令將被布局中的內(nèi)容替換。
@yield
指令還接受一個(gè)默認(rèn)值作為第二個(gè)參數(shù)。如果被 「yield」的片段未定義,則該默認(rèn)值被渲染:
@yield('content', View::make('view.name'))
Blade 視圖可以使用全局 view
助手自路由中返回:
Route::get('blade', function () {
return view('child');
});
4.2.3 組件 & 插槽
組件和插槽提供了與片段和布局類似的好處;不過組件和插槽的思維模型更易于理解。我們先來看一個(gè)可復(fù)用的「alert」組件,我們想在應(yīng)用中復(fù)用它:
注:插槽定義好,組件必須要實(shí)現(xiàn)其內(nèi)容
<!-- /resources/views/alert.blade.php -->
<div class="alert alert-danger">
{{ $slot }}
</div>
{{ $slot }}
變量將包含我們想要注入到組件的內(nèi)容?,F(xiàn)在,我們使用 Blade 的 @component
指令構(gòu)建這個(gè)組件:
@component('alert')
<strong>Whoops!</strong> Something went wrong!
@endcomponent
若要指示 Laravel 從組件的給定數(shù)組中加載存在的第一個(gè)視圖,可以使用 componentFirst
指令:
@componentFirst(['custom.alert', 'alert'])
<strong>Whoops!</strong> Something went wrong!
@endcomponent
有時(shí)候?yàn)橐粋€(gè)組件定義多個(gè)插槽是很有用的。修改 alert 組件以允許其注入 「title」。命名插槽可以通過與其匹配的 「回顯」 變量顯示:
<!-- /resources/views/alert.blade.php -->
<div class="alert alert-danger">
<div class="alert-title">{{ $title }}</div>
{{ $slot }}
</div>
現(xiàn)在,我們能夠使用 @slot
指令向命名插槽注入內(nèi)容。不在 @slot
指令內(nèi)的內(nèi)容都將傳遞給組件中的 $slot
變量:
@component('alert')
@slot('title')
Forbidden
@endslot
You are not allowed to access this resource!
@endcomponent
4.3 加載靜態(tài)資源
采用函數(shù)
asset();//直接定位到public下面
publi_path()
各位同學(xué)以上就是 Laravel 視圖的全部?jī)?nèi)容,欲知更多內(nèi)容,請(qǐng)聽下章詳解。