Laravel-視圖View&Blade

View與視圖

  • 將PHP轉成HTML檔之後傳出

舊有的PHP檔案

  • 沒有Controller
  • Model負責資料查詢
  • View負責處理HTML

Laravel的View設計

  • 負責儲存HTML,並將要顯⽰動態資料的地⽅留出來,等傳⼊後替換

Blade樣板引擎

  • 檔名需為*.blade.php
  • 編譯成一般PHP
  • 啟用快取以加快回應速度

為何有樣板的需求?

  • 每個⾴⾯都會有共同的內容,⽐如選單
  • 舊有PHP的應對作法
  • 透過include語法,可以將其他⾴⾯檔案嵌⼊到當前畫⾯內

那繼續使⽤include不好嗎??

  • 單純複製貼上,並無容器的概念
  • 無法將動態資料傳遞進去,只能顯⽰ 固定內容

Laravel樣板引擎

  • 可傳遞參數

    ⽅便傳遞參數並執⾏所有PHP內建函式與Laravel語法

  • ⾴⾯加入親屬關係

    繼承變得簡單,重複的部分都移到⽗視圖去,不同的部分才留在⼦視圖

  • Blade導⼊

    採⽤Blade作為引擎

Laravel的View設計

  • 採⽤MVC架構來進⾏設計,View檔案都放在resources/views資料夾內
  • 所有View的檔案以*.blade.php作為結尾,內容就是⼀般的HTML程式碼加上Blade語法

回傳View結果

  • ⽤view()這個helper function直接回傳,特別路徑要正確,路徑⽤『 . 』來區隔,不需寫.blade.php
class UserController extends Controller{
public function index(){
//檔案為resources/views/users的index.blade.php
return view(‘users.index’);
}
}

Blade語法

Blade指令1

@ 開頭 • 樣板控制@yield . @extends • 程式邏輯控制@if . @foreach { 開頭 • 輸出內容{{ . {!! • 註解 {{- -

Blade指令2

挖洞 @yield(‘{section name}’)

繼承 @extends(‘{view name}’)

包含 @include(‘{view name}’)

填洞 • @section(‘{yield name}’ , ’{ string }’) • @section(‘{yield name}’) • @stop

⽗Blade版⾯配置

<head>
<title>My Site | @yield(‘title’,’HomePage’)</title>
</head>
<body>
 @yield(‘content’)
@include(‘include’,[‘text’=>’master page’])
@section(‘footerScripts’)
 <script src=“app.js”></script>
@show

⼦Blade版⾯配置

@extends(‘layouts.master’)         繼承
@section(‘title’,’About’)          取代,第⼆參數為預設
@section(‘content’)                充填
@endsection
<div>…</div>
@section(‘footerscripts’)
@endsection
@parent                            繼承⽗Blade再充填
<script src=“dashboard.js”></script>

控制結構

• @if . @elseif . @else . @endif(假如) • @unless . @endunless (除⾮) • @switch(當)

邏輯控制

迴圈 •@for( $i = 0 ; $i<10 ; $++ ) @endfor •@foreach( $tasks as $task ) @endforeach •@forelse @empty @endforelse •@while(條件) @endwhile

foreach/forelse的$loop

是⼀個stdClass物件,具有以下特性

index 項⽬索引,從0開始 last 判斷是否為最後⼀個項⽬
iteration 項⽬索引,從1開始 first 判斷是否為第⼀個項⽬
remaining 還剩多少個項⽬ depth 迴圈有幾層深
count 項⽬數量 parent 參考上層迴圈的$loop

輸出資料

{{ $string }} • 輸出前會做跳脫,安全預設 • {{ $name ?? ‘Default’ }}

{!! $html !!} 輸出不會做跳脫,可⽤於輸出 HTML或JS

想要顯⽰{{ ⽤@{{ raw data}}輸出

不確定是否有值,需要給預設值 ⽤{{ $title ?? ‘Default’ }}

傳送值到多個View

全域共⽤變數

//app/Providers/AppServiceProvider.php

• 讓你應用程式內的每一個視圖全域共用一個變數 • 使用view物件的share()函式 • 需要寫在Provider的boot()方法 • 可使用預設的AppServiceProvider • 8.x版本不需要再加上defaultStringLength(191);

多視圖共⽤變數

//app/Providers/AppServiceProvider.php

• 讓多個視圖共⽤變數 • 使⽤view物件的composer()函式 • 可寫在Provider的boot()⽅法 • 可使⽤預設的AppServiceProvider

View&Blade練習作業 • ☐嘗試⾃⼰做出電⼦商務⾸⾴的blade視圖,並從Controller回傳 • ☐優化⾃⼰的blade,把重複部分分離成master.blade.php,以繼承的⽅式改寫 • ☐練習課程所有提到的Blade指令 • ☐實驗{{ }} 和{!! !!}}這兩種輸出指令的不同 • ☐嘗試兩種將值傳到多個View的作法,並思考其使⽤時機


Blade指令

樣板控制

@yield(‘{section name}’)

@section(‘{section name}’)
    <div>可以選擇性繼承的內容</div>
@show

填洞

填單一內容使用
@section(‘{yield name}’ , ’{ string }’)

填複雜內容使用
@section(‘{yield name}’)
@stop

包含 
@include(‘{view name}’,['key1'=>'value1','key2'=>'value2'])

繼承,通常寫在子視圖的頭 
@extends(‘{view name}’)

程式邏輯控制 Comment

條件判斷式

假如
@if
@elseif
@else 
@endif

除非
@unless 
@endunless

當
@switch

@endswitch

迴圈

@foreach( $tasks as $task ) 
    逐一取出陣列的內容來加以處理
@endforeach

@for( $i = 0 ; $i<10 ; $++ ) 

@endfor

@forelse( $tasks as $task )

@empty 
    目前沒有工作
@endforelse

@while

@endwhile

隱含變數 $loop

$loop->index 索引值,從0開始 $loop->iteration 第幾個,從1開始 $loop->remaining 還剩幾個 $loop->count 總共幾個 $loop->last 是否為最後 $loop->first 是否為第一

輸出內容

{{ 內容遇到程式碼會當純文字處理 }} {!! 內容遇到程式碼會渲染並執行 !!} {{- - 註解 –}} @{{ 顯示Blade語法 }}

課程範例

//resources/views/master.blade.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>
    @yield('title')
    </title>
</head>
<body>
    
    @yield('content')
    
    
    @section('js')
        <script src="js/1.js" />
    @show
    <p>js結束</p>
</body>
</html>

//resources/views/index.blade.php
@extends('layouts.master')


@section('js')
    <script src="2.js" />
    @parent
@stop

@section('title','首頁')
    
@section('content')
<div class="container clearfix">
    我的內容
</div>

 @foreach ($data as $tmp)
     <h2>{{ $tmp }}</h2>
     <h3>{{ $loop->index }} </h3>
 @endforeach
@stop


//routes/web.php
Route::get('/index','HomeController@index');

//app/Http/Controllers/HomeController.php
public function index()
{
    return view('index');
}

多視圖共享

//全域共享
view()->share('tel','0212345678');

//部分共享
view()->composer(['items.*'],function($view){
    $view->with('address','中山路一號');
});

參考資料