Laravel 入門:來認識 Blade 吧


Posted by SimonAllen on 2020-09-24

Blade 是什麼?

Blade 是 Laravel 框架的 Template Engine。關於 Template Engine 可參考維基百科說明。

在 Server-side MVC 架構下按語言、框架不同,通常會有個 Template Engine 來幫助處理前端 View 的開發,例如在 Node.js 可以選擇使用 PugEJSASP.NET MVC 使用 Razor ..等等。

除了(能透過 Controller)取得 Model 來的資料,也可以透過語法去做到邏輯判斷、迴圈渲染、HTML 段落 (Template) 拆分與引用,以此做到開發上 View 相關程式碼的共用、繼承,並最終可以 build 成 完整的 HTML。

需要擔心效能嗎?

按照 Laravel 文件說法,Blade 和其他 PHP Template Engine 不同之處在於 Blade 不限制在檔案內使用原生 PHP Code。且所有 Blade View 實際上還是被 Compile 成原生的 PHP 而非 HTML,效能不至於有太大影響,不用太擔心這個問題。

檔案命名

Blade 檔案通常放在resources/views 下,並使用 .blade.php 作為文件的副檔名後輟名稱。

例如:

  • Blade 檔案:header.blade.phpfooter.blade.php
  • 一般 PHP: header.phpfooter.php

官方範例:拆分 Layout

使用 Blase 拆分各個 Templete Layout,最重要的就是 @section@yield 兩個語法了。

首先我們在 resource/views/ 建立一個子資料夾 layout,並在layout 資料夾裡頭建立一個 app.blade.php:

  • 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>

接著在 resource/views/ 建立一個 child.blade.php

  • resource/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

最後到 /routes/web.php 加入這段

  • routes/web.php
Route::get('/child', function () {
    return view('child');
});

接著到網址輸入http://127.0.0.1:8000/child
可以看到網頁正常顯示

這個過程發生了什麼事呢?在上面的程式碼裡,我們看到了 @extends@yield@section@parent@show

 使用 @extends() 繼承 Layout View

我們在 child.blade.php 的開頭@extends('layouts.app'),繼承了app.blade.php 的內容,但 @extends() 括弧內的 layouts.app 是什麼意思?

layouts.app 其實指的是 layouts 資料夾下的 app 這個 blade 檔案,也就是 app.blade.php

若我們將 app.blade.php 改名成 test.blade.php,那 @extends('layouts.app') 就要改成 @extends('layouts.test')

也就是說資料夾的階層區隔不是用 / 而是用 .,若是 app.blade.phpchild.blade.php 同一層,那麼 @extends 就要寫成 @extends('app')


總來得來說,因為使用了 @extends() 繼承了 app.blade.php ,我們可以在接下來用 @yield 和 @section 來設定填滿 app.blade.php 提供的 HTML 內容。

@yield 與 @section

@yield@section 定義了 View 的內容,使用@yield('title') 對應到了 @section('title'),靠的是彼此第一個參數 'title' 的聯繫,而第二個參數(這裡傳入'Page Title') 會被傳到 @yield('title')設定的位置,也就是變成

 <title>App Name - Page Title <title>

@section 與 @show

@section 字面含義,@section 表示一個段落,@show 表示執行到此時,將該 @section 中的內容顯示到頁面上,我們也可以重新覆蓋這個段落內容。

@section 與 @endsection

若使用 @section 要再加上其他的 HTML code 或 Blade 語法,亦可以在@section 後面加上 @endsection,將我們要的內容置於其中。

@section 與 @parent

當我們用 @extends 繼承了某個 Layout View,並在 @section@endsection 定義了其他段落,預設會將 @extends 同區塊內容覆蓋掉,這時可以加入 @parent 同時呈現原本繼承而來的內容。

顯示數據

使用 {{ }} 顯示資料

Blade 數據顯示常見形式是使用 Mustache 語法(雙大括號) {{ }} 來顯示資料,若前端有寫過 Vue,看到 {{ }} 應該會倍感親切。例如現在有個變數 $name,要將其顯示只要這樣:

<h1>{{ $name }}</h1>

和其他文字放一起也沒問題

<h1>Hello,{{ $name }} </h1>

{{ }} 不僅能在 HTML tag 內顯示資料,也可以置入 tag 的 attribute 來達到替換屬性,
例如若打開 Laravel 專案預設的 welcome.blade.php ,可以看到 a 標籤的 href 如下:

 <a href="{{ url('/home') }}">Home</a>

顯示流程

@if 、 @elseif 與 @else

@if (count($records) === 1)
    I have one records
@elseif (count($records) > 1)
    I have more records
@else
    I don't have any records
@endif

同樣的 code ,原生 PHP 則是會這樣寫:

<?php if(count($records) === 1): ?>
    I have one records
<?php elseif(count($records) === 1): ?>
    I have more records
<?php else: ?>
    I don't have any records
<?php endif; ?>

所以 Blade 只是簡化了語法的部分,讓我們更好撰寫對畫面的顯示邏輯。

條列式渲染資料

面對多筆資料的條列式渲染,React 一般會使用 JavaScript .map() 、 Vue 一般使用 v-for ,那對於在 Server-side 的 Blade 呢?

@for 與 @endfor

相較於用 PHP 原生 for 迴圈的條列式渲染(迭代), Blade 幫我們簡化了語法,使用 @for 可以做到一樣的事情。

@for ($i = 0; $i < 10; $i++)
    The current value is {{ $i }}
@endfor

@foreach

比起用 for 去跑,也可以使用 foreach 來條列渲染,使用 @foreach@endforeach 即可,同樣也是開頭加上 @ 符號就好。

@foreach ($users as $user)
    <p>This is user {{ $user->id }}</p>
@endforeach

@forelse

初次看到 @forelse ,還要想一下 PHP 或 JS 有沒有類似 forelse 這個語法。
事實上 @forelse 是 Laravel Blade 包過的語法,當我們在使用 @for@foreach 迭代時,可能還會搭配 @if@else 去做到顯示邏輯的劃分:有資料(成立)時顯示什麼?沒有資料(不成立)顯示什麼?

例如:

@if ($users->count())
  @foreach ($users as $user)
    <li>{{ $user->name }}</li>
  @endforeach
@else
  <p>No users</p>
@endif

改用 @forelse

@forelse ($users as $user)
    <li>{{ $user->name }}</li>
@empty
    <p>No users</p>
@endforelse

有資料顯示 <li>{{ $user->name }}</li> ,沒有就給個<p> tag 和 No users 的文字,這樣語法就清晰許多了。

其他

註解

Blade 內當然也可以使用註解,並且這個註解不會在 Web client 端顯示出來:

{{-- 這是註解這是註解這是註解這是註解這是註解 --}}

auth 身份驗證

@auth
    <p>已登入</p> 
@endauth

@guest
    <p>尚未登入</p> 
@endguest

現在什麼時候會用到 Blade?

現代前端在前後端專案分離架構下,使用 Server-side Template Engine 機會降低不少,即便前後端專案沒分離多半也是在 Template Engine 上插入 React 或 Vue 的 Component,其他 View 邏輯一樣是用前端 Root Component 接著在這個元件內importexport 元件寫來寫去其他的 Component。

但不可否認,若今天是一個小型的專案,直接從後端開始寫,使用 Blade 來處理前端也不會比較慢或差,前端也不必搞 SSR,因為就已經是 Server-side 的技術了,在 View 層去接資料,前端也不用等載入頁面後才 AJAX 資料一次。


#筆記 #Laravel







Related Posts

Day07:V8 bytecode 系列文總結

Day07:V8 bytecode 系列文總結

Leetcode 刷題 pattern - Fast & Slow Pointer

Leetcode 刷題 pattern - Fast & Slow Pointer

Day5 跟一般的指令可不一樣啊!跟我所認識的指令不同啊!

Day5 跟一般的指令可不一樣啊!跟我所認識的指令不同啊!


Comments