【Laravel】テンプレートエンジン「Blade」の構文
2019/12/23
LaravelのBladeテンプレートの基本構文をまとめます。
if, for, foreach, whileなど、一通りの構文が揃っているので、不自由はなさそうな印象ですが、果たして。
Smartyより使いやすいテンプレートエンジンであることを祈る…!
Bladeの構文 / データ表示
(自動的に)エスケープする
値を埋め込む(表示する)には「{{ }}」を用います。
Bladeの{{ }}記法はXSS対策として、自動的にPHPのhtmlspecialchars関数を通しエスケープ処理されます。
1 |
{{ $name }} |
エスケープしない
{{ }}は自動的にエスケープされますが、エスケープ処理されてほしくない場合は {{!! … !!}} を用います。
1 |
{{!! $name !!}} |
コメント
{{-- --}} で書かれたテキストはコメントとして扱われます。
1 |
{{-- このコメントはHTML上には表示されません --}} |
改行を含む場合
改行が含まれる値を表示したいときは、以下のように記述します。
e() はヘルパ関数で、htmlspecialchars関数を実行します。
1 |
{!! nl2br(e($message)) !!} |
実例
アクション
プロジェクトディレクトリ\app\Http\Controllers\HelloController.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/** * ビューのテスト * 改行 */ public function newline() { $message = 'あいうえお かきくけこ さしすせそ'; $data = [ 'message' => $message ]; return view('hello.newline', $data); } |
テンプレート
プロジェクトディレクトリ\resources\views\hello\newline.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>ビューのテスト</title> </head> <body> <h1>ビューのテスト</h1> <h2>改行</h2> <p>{!! nl2br(e($message)) !!}</p> </body> </html> |
ルーティング
プロジェクトディレクトリ\routes\web.php
1 |
Route::get('/hello/newline', 'HelloController@newline'); |
結果
制御構文
if文
if文の構文には、@if、@elseif、@else、@endifディレクティブを使用します。
これらの使い方はPHPの構文と同じです。
条件がTRUEの場合に表示する
1 2 3 |
@if ($flg === 1) flgは1です @endif |
条件によって異なる表示をする
1 2 3 4 5 |
@if ($flg === 1) フラグは1です @else フラグは1ではありません @endif |
複数の条件を設定する
1 2 3 4 5 6 7 |
@if (count($records) === 1) 1レコードあります @elseif (count($records) > 1) 複数レコードあります @else レコードはありません @endif |
条件がFALSEの場合に表示する
1 2 3 |
@unless (Auth::check()) あなたはログインしていません。 @endunless |
if文と逆なので、@elseを用意した場合は条件がTRUEの場合に表示します。
変数が空の場合に表示
条件とした変数が空の場合に表示を行います。
@elseを用意した場合は、変数が空でない(値が設定されている)ときに表示されます。
1 2 3 |
@empty($records) "records"は「空」です @endempty |
変数が定義済みの場合に表示
変数そのものが定義済みかどうかを確認します。変数が定義済みかつ、nullではない場合に表示します。
@elseを用意した場合は、変数が未定義だったときに表示します。
1 2 3 |
@isset ($records) "records"は定義済みでnullでない @endisset |
実例
アクション
プロジェクトディレクトリ\app\Http\Controllers\HelloController.php
1 2 3 4 5 6 7 8 9 10 11 12 |
/** * ビューのテスト * 改行 */ public function if() { $records = [ 'one', 'two', 'three', 'four', 'five', ]; return view('hello.if', ['data' => $records]); } |
テンプレート
プロジェクトディレクトリ\resources\views\hello\if.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>ビューのテスト</title> </head> <body> <h1>ビューのテスト</h1> <h2>if文</h2> <p> @if (count($data) === 1) 1レコードあります @elseif (count($data) > 1) 複数レコードあります @else レコードはありません @endif </p> </body> </html> |
ルーティング
プロジェクトディレクトリ\routes\web.php
1 |
Route::get('/hello/if', 'HelloController@if'); |
結果
switch文
@switch、@case、@break、@default、@endswitchディレクティブを使用し、switch文を構成できます。
1 2 3 4 5 6 7 8 9 10 11 12 |
@switch($i) @case(1) 最初のケース @break @case(2) 2番めのケース @break @default デフォルトのケース @endswitch |
実例
アクション
プロジェクトディレクトリ\app\Http\Controllers\HelloController.php
1 2 3 4 5 6 7 8 9 10 |
/** * ビューテスト * switch文 */ public function switch() { $i = 2; return view('hello.switch', ['data' => $i]); } |
テンプレート
プロジェクトディレクトリ\resources\views\hello\switch.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>ビューのテスト</title> </head> <body> <h1>ビューのテスト</h1> <h2>switch文</h2> <p> @switch($data) @case(1) 最初のケース @break @case(2) 2番目のケース @break @default デフォルトのケース @endswitch </p> </body> </html> |
ルーティング
プロジェクトディレクトリ\routes\web.php
1 |
Route::get('/hello/switch', 'HelloController@switch'); |
結果
繰り返し
for文
1 2 3 |
@for ($i=0; $i<5; $i++) {{ $i }} @endfor |
基本的にPHPのfor文と変わりなしですね。
実例
アクション
プロジェクトディレクトリ\app\Http\Controllers\HelloController.php
1 2 3 4 5 6 7 8 |
/** * ビューテスト * for文 */ public function for() { return view('hello.for'); } |
テンプレート
プロジェクトディレクトリ\resources\views\hello\for.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>ビューのテスト</title> </head> <body> <h1>ビューのテスト</h1> <h2>for文</h2> <p> @for ($i=0; $i<5; $i++) {{$i}}, @endfor </p> </body> </html> |
ルーティング
プロジェクトディレクトリ\routes\web.php
1 |
Route::get('/hello/for', 'HelloController@for'); |
結果
foreach文
1 2 3 |
@foreach ($users as $user) <p>これは {{ $user->id }} ユーザーです。</p> @endforeach |
実例
アクション
プロジェクトディレクトリ\app\Http\Controllers\HelloController.php
1 2 3 4 5 6 7 8 9 10 11 12 |
/** * ビューテスト * foreach文 */ public function foreach() { $records = [ 'one', 'two', 'three', 'four', 'five', ]; return view('hello.foreach', ['data' => $records]); } |
テンプレート
プロジェクトディレクトリ\resources\views\hello\foreach.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>ビューのテスト</title> </head> <body> <h1>ビューのテスト</h1> <h2>foreach文</h2> @foreach ($data as $key => $val) <p>{{$key}}, {{$val}}</p> @endforeach </body> </html> |
ルーティング
プロジェクトディレクトリ\routes\web.php
1 |
Route::get('/hello/foreach', 'HelloController@foreach'); |
結果
foreach-else
foreach文にelseを追加した場合の処理です。
配列から順に値を取り出して処理を繰り返していく点は @foreach と同じです。
値をすべて取り出し終え、取り出せなくなった時に @empty にある処理を実行して繰り返しを終了します。
1 2 3 4 5 |
@forelse ($users as $user) <li>{{ $user->name }}</li> @empty <p>ユーザーなし</p> @endforelse |
while文
引数に条件を設定し、その条件がtrueの場合に表示を行います。
whileでは、実行時に条件で使っている変数などの値が変化しなければ、無限ループとなってしまうため、ディレクティブ内で何らかの処理を実行する必要があるので注意。
1 2 3 |
@while (true) <p>無限ループ中</p> @endwhile |
おお、なんてサンプルンなんだ…。
@breakと@continue
PHPの繰り返し構文ではbreakやcontinueといった制御が可能ですが、Bladeにも同様のワードが用意されており、制御が可能です。
繰り返しを使用する場合、ループを終了するか、現在の繰り返しをスキップすることもできます。
@break
@breakが出現した時点で繰り返しディレクティブが中断されます。
1 2 3 4 5 6 7 |
@foreach ($users as $user) <li>{{ $user->name }}</li> @if ($user->id == 5) // ループ終了 @break @endif @endforeach |
実例
アクション
プロジェクトディレクトリ\app\Http\Controllers\HelloController.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/** * ビューテスト * break文 */ public function break() { $users = [ ['id'=> 1, 'name'=> 'Alex'], ['id'=> 2, 'name'=> 'Billy'], ['id'=> 3, 'name'=> 'Charlie'], ['id'=> 4, 'name'=> 'Daniel'], ['id'=> 5, 'name'=> 'Edward'], ['id'=> 6, 'name'=> 'Fredrick'], ]; return view('hello.break', ['data' => $users]); } |
テンプレート
プロジェクトディレクトリ\resources\views\hello\break.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>ビューのテスト</title> </head> <body> <h1>ビューのテスト</h1> <h2>break</h2> <ul> @foreach ($data as $user) <li>{{$user['name']}}</li> @if ($user['id'] == 3) @break @endif @endforeach </ul> </body> </html> |
ルーティング
プロジェクトディレクトリ\routes\web.php
1 |
Route::get('/hello/break', 'HelloController@break'); |
結果
@continue
条件が当てはまる時にループをスキップします。
1 2 3 4 5 6 7 |
@foreach ($users as $user) @if ($user->id == 3) // ループをスキップ @continue @endif <li>{{ $user->name }}</li> @endforeach |
実例
アクション
プロジェクトディレクトリ\app\Http\Controllers\HelloController.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/** * ビューテスト * continue文 */ public function continue() { $users = [ ['id'=> 1, 'name'=> 'Alex'], ['id'=> 2, 'name'=> 'Billy'], ['id'=> 3, 'name'=> 'Charlie'], ['id'=> 4, 'name'=> 'Daniel'], ['id'=> 5, 'name'=> 'Edward'], ['id'=> 6, 'name'=> 'Fredrick'], ]; return view('hello.continue', ['data' => $users]); } |
テンプレート
プロジェクトディレクトリ\resources\views\hello\continue.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>ビューのテスト</title> </head> <body> <h1>ビューのテスト</h1> <h2>continue</h2> <ul> @foreach ($data as $user) @if ($user['id'] == 3) @continue @endif <li>{{$user['name']}}</li> @endforeach </ul> </body> </html> |
ルーティング
プロジェクトディレクトリ\routes\web.php
1 |
Route::get('/hello/continue', 'HelloController@continue'); |
結果
↑ 3番目の「Charlie」が抜けています
渡す配列を、オブジェクトにするテスト
Blade構文の例にあるように、オブジェクトで制御する方法です。
余談ですが、最近のフレームワークではDBの結果がオブジェクト形式で帰ってくるなどの例がありますが、PHPの場合は自力で作成する場合は連想配列のほうが使い勝手が良さそうな気がしますね。
アクション
プロジェクトディレクトリ\app\Http\Controllers\HelloController.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/** * ビューテスト * continue文 オブジェクトで渡す方法 */ public function continue_obj() { $users = [ (object) ['id'=> 1, 'name'=> 'Alex'], (object) ['id'=> 2, 'name'=> 'Billy'], (object) ['id'=> 3, 'name'=> 'Charlie'], (object) ['id'=> 4, 'name'=> 'Daniel'], (object) ['id'=> 5, 'name'=> 'Edward'], (object) ['id'=> 6, 'name'=> 'Fredrick'], ]; return view('hello.continue_obj', compact('users')); } |
テンプレート
プロジェクトディレクトリ\resources\views\hello\continue_obj.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>ビューのテスト</title> </head> <body> <h1>ビューのテスト</h1> <h2>continue obj</h2> <ul> @foreach ($users as $user) @if ($user->id == 4) @continue @endif <li>{{$user->name}}</li> @endforeach </ul> </body> </html> |
ルーティング
プロジェクトディレクトリ\routes\web.php
1 |
Route::get('/hello/continue_obj', 'HelloController@continue_obj'); |
結果
↑ 4番目の「Daniel」が抜けています
ループ変数
繰り返し中は、$loop変数が使用できます。この変数により、現在のループインデックスや繰り返しの最初/最後なのかなど、便利な情報にアクセスできます。
Smartyでもありましたね、これ。
プロパティ | 説明 |
---|---|
$loop->index |
現在のループのインデックス(初期値0) |
$loop->iteration |
現在の繰り返し数(初期値1) |
$loop->remaining |
繰り返しの残り数 |
$loop->count |
繰り返し中の配列の総アイテム数 |
$loop->first |
ループの最初の繰り返しか判定 |
$loop->last |
ループの最後の繰り返しか判定 |
$loop->even |
これは偶数回目の繰り返しか判定 |
$loop->odd |
これは気数回目の繰り返しか判定 |
$loop->depth |
現在のループのネストレベル |
$loop->parent |
ループがネストしている場合、親のループ変数 |
1 2 3 4 5 6 7 8 9 10 11 |
@foreach ($users as $user) @if ($loop->first) これは最初の繰り返し @endif @if ($loop->last) これは最後の繰り返し @endif <p>これは {{ $user->id }} ユーザーです。</p> @endforeach |
@foreachを二重に(ネスト)した場合では、親のループの$loop変数にparentプロパティを通じアクセスできます。
1 2 3 4 5 6 7 |
@foreach ($users as $user) @foreach ($user->posts as $post) @if ($loop->parent->first) これは親のループの最初の繰り返しだ @endif @endforeach @endforeach |
PHP
PHPコードをビューへ埋め込むと便利な場合もあります。
Bladeの@phpディレクティブを使えば、テンプレートの中でプレーンなPHPブロックを実行できます。
1 2 3 |
@php // @endphp |
参考にしたサイト
迷ったら公式。
https://readouble.com/laravel/5.8/ja/blade.html