範本語法 v2
範本 v2 是 Zittme 建議使用的範本語法。它在 Blade 風格的指令上加入了 Zittme 獨有的功能,並可在同一個檔案中與 v1 語法相容。
宣告版本
.html檔案:第一行寫@version(2)(或<config version="2" />).blade.php檔案:自動為 v2(可獲得 IDE 語法醒目提示)
@version(2)
<div class="my-skin">
<h1>{{ $title }}</h1>
</div>輸出
| 語法 | 意義 |
|---|---|
{{ $var }} | 經 HTML 跳脫後輸出(預設) |
{!! $var !!} | 不跳脫,原樣輸出 |
{$var} | v1 相容輸出 |
{!! !!} 請只用於像編輯器內文這類核心已淨化過的 HTML。若將使用者輸入原樣輸出,就會造成 XSS。跳脫會辨識上下文(HTML/JS)並自動處理。
篩選器
可以在輸出後接上 |篩選器,也能串接多個。
{{ $title|upper }}
{{ $timestamp|date:'Y-m-d' }}
{{ $price|number_format }}
{{ $tags|join:', ' }}主要篩選器:autoescape escape noescape escapejs json strip_tags trim urlencode lower upper nl2br join:separator date:format number_format:decimals number_shorten link
條件
@if ($is_logged)
...
@elseif ($guest_allowed)
...
@else
...
@endif也有專用的條件指令。
| 指令 | 意義 |
|---|---|
@isset($var) ~ @endisset | 變數存在時 |
@empty($var) ~ @endempty | 為空時 |
@admin ~ @endadmin | 為最高管理員時 |
@auth ~ @endauth | 已登入時(@auth('manager') 為管理權限) |
@guest ~ @endguest | 未登入時 |
@can('view') ~ @endcan | 擁有該權限時(也支援 @cannot、@canany([...])) |
@desktop / @mobile | 區分裝置 |
迴圈
@foreach ($list as $key => $item)
<li>{{ $item->title }}</li>
@endforeach
@forelse ($list as $item)
<li>{{ $item->title }}</li>
@empty
<li>항목이 없습니다</li>
@endforelse也支援 @for @while @switch/@case/@break/@default @continue。
迴圈中可使用 $loop 變數:$loop->index(從 0 開始) $loop->iteration(從 1 開始) $loop->count $loop->first $loop->last $loop->even $loop->odd $loop->depth $loop->parent
@foreach ($list as $item)
<li class="@if ($loop->first) is-first @endif">{{ $loop->iteration }}. {{ $item->title }}</li>
@endforeachHTML 屬性輔助函式
<div @class(['base', 'is-on' => $active, 'is-mine' => $item->mine])>...</div>
<div @style(['color: red', 'display: none' => $hidden])>...</div>
<input type="checkbox" @checked($is_checked) />
<option value="1" @selected($val == 1)>하나</option>
<input @disabled($locked) @readonly($readonly) @required($must) />v1 的 checked="checked"|cond="..." 寫法也仍然有效。
PHP 程式碼
@php
$count = count($list);
$first = $count ? reset($list) : null;
@endphp
{@ $total = $count + 1; }- 範本變數預設是參照 Context 的共用狀態。像
\$var這樣加上反斜線,就會成為該範本專屬的區域變數。閉包的參數・use 繫結也使用\$。 - 在
{@ ... }中也可以用foreach (...):/endforeach;風格開啟與關閉區塊。
註解
{{-- 템플릿 주석: 출력에서 제거됩니다 --}}
<!--// v1 스타일 주석: 역시 제거됩니다 -->
<!-- 일반 HTML 주석: 출력에 남습니다 -->注意:{{-- --}} 註解務必寫在同一行。若跨多行撰寫,剖析器無法完整移除,可能導致伺服器錯誤(500)。實際上曾因這個問題發生過故障。多行說明請使用 HTML 註解(<!-- -->)。
引入其他範本
@include('_header')
@include('sub/box')
@include('_card', ['title' => $t, 'body' => $b]) {{-- 변수 전달 --}}
<include src="_promo" if="$show_promo" /> {{-- 조건부 포함 --}}
<include src="_banner" unless="$is_admin" />- 傳遞變數時,被引入的範本不使用 Context,而只使用傳入的變數(像元件一樣使用)。
- 條件式引入透過
<include>標籤的if/when/cond/unless屬性達成。 - v1 的
<include target="..." />也有效。
載入資源:@load
@load('css/skin.css')
@load('css/skin.scss', $vars) {{-- SCSS 변수 전달 --}}
@load('js/skin.js')
@load('js/lazy.js', 'body') {{-- body 끝에서 로드 --}}
@load('^/common/js/plugins/URI.js') {{-- ^ 는 사이트 루트 --}}
@load('../lang/') {{-- 언어 파일 디렉터리 --}}
@unload('foo/bar.js') {{-- 로드 취소 --}}CSS 可用額外參數指定 media・順序,JS 可指定 head/body・順序。
產生 URL
<a href="@url('act', 'dispMemberInfo')">내 정보</a>
<a href="{{ getUrl('', 'mid', $mid, 'act', 'dispBoardWrite') }}">글쓰기</a>@url(...) 與 getUrl(...) 的作用相同。只要記住一條規則。
- 只變更目前頁面參數的連結(分頁・排序):不帶第一個參數,
getUrl('page', $n) - 前往其他畫面的連結:第一個參數務必給
'',從空白 URL 重新產生。否則目前請求的參數會全部被帶過去。
若動作已宣告路由,會自動產生短網址。
其他指令
| 指令 | 意義 |
|---|---|
@csrf | 在表單中插入 CSRF 權杖欄位 |
@json($array) | 輸出對 JS 安全的 JSON(自動辨識上下文) |
@lang('key') | 輸出語言字串(@lang('module.key')) |
@use('Namespace\Class', 'Alias') | 宣告類別別名。之後可用 {{ Alias::method() }} |
@widget('widget-name', $args) | 插入小工具 |
@once ~ @endonce | 即使在迴圈中也只執行一次 |
@verbatim ~ @endverbatim | 此區段不解析範本語法 |
@dump($var) / @dd($var) | 除錯輸出(dd 輸出後中止) |
@push('name') ~ @endpush / @stack('name') | 收集內容並在一處輸出 |
@error('validator-id') ~ @enderror | 顯示表單驗證錯誤 |
v2 不支援的功能
- Blade 的範本繼承(
@extends@yield@section)與插槽(@slot@inject) - v1 的
<block>標籤、任意標籤上的loop/cond屬性(<include>的條件屬性除外)
需要 v1 語法的既有檔案維持原狀即可。請避免在同一個檔案中混用兩代語法。
實戰中常踩的陷阱
以下項目來自實際的故障案例。
- 禁止多行
{{-- --}}註解(請參閱上方註解一節)。這是伺服器 500 的常見原因。 - 在範本中直接呼叫靜態方法時,請以
@use宣告別名,並用別名呼叫。若在屬性值中直接呼叫完整命名空間路徑,編譯會出錯,可能產生像%7B...%7D這樣的損壞連結。最安全的做法是在控制器中以Context::set()傳遞值。 Context::set()會覆蓋同名的請求變數。在 proc 動作中讀取表單值時,直接讀取$_POST較為安全。- CSS 選擇器優先順序:共用 CSS 的
.wrap a { color: inherit }比新建的單一.my-link更強。若連結顏色沒有套用,請像.wrap a.my-link這樣提高優先順序。