イントロダクション
BladeはシンプルながらパワフルなLaravelのテンプレートエンジンです。他の人気のあるPHPテンプレートエンジンとは異なり、ビューの中にPHPを直接記述することを許しています。全BladeビューはPHPへコンパイルされ、変更があるまでキャッシュされます。つまりアプリケーションのオーバーヘッドは基本的に0です。Bladeビューには.blade.php
ファイル拡張子を付け、通常はresources/views
ディレクトリの中に設置します。
テンプレートの継承
レイアウト定義
Bladeを使用する主な利点は、テンプレートの継承とセクションです。初めに簡単な例を見てください。通常ほとんどのアプリケーションでは、数多くのページを同じ全体的なレイアウトの中に表示するので、最初は"master"ページレイアウトを確認しましょう。レイアウトは一つのBladeビューとして、簡単に定義できます。
<!-- resources/views/layouts/master.blade.phpとして保存 -->
<html>
<head>
<title>アプリ名 - @yield('title')</title>
</head>
<body>
@section('sidebar')
ここがメインのサイドバー
@show
<div class="container">
@yield('content')
</div>
</body>
</html>
ご覧の通り、典型的なHTMLマークアップで構成されたファイルです。しかし、@section
や@yield
ディレクティブに注目です。@section
ディレクティブは名前が示す通りにコンテンツのセクションを定義し、一方の@yield
ディレクティブは指定したセションの内容を表示するために使用します。
これでアプリケーションのレイアウトが定義できました。このレイアウトを継承する、子のページを定義しましょう。
レイアウト拡張
子のページを定義するには、「継承」するレイアウトを指定する、Blade
@extends
ディレクティブを使用します。Bladeレイアウトを拡張するビューは、@section
ディレクティブを使用し、レイアウトのセクションに内容を挿入します。前例にあるようにレイアウトでセクションを表示するには@yield
を使用します。
<!-- resources/views/child.blade.phpとして保存 -->
@extends('layouts.master')
@section('title', 'Page Title')
@section('sidebar')
@@parent
<p>ここはメインのサイドバーに追加される</p>
@endsection
@section('content')
<p>ここが本文のコンテンツ</p>
@endsection
この例のsidebar
セクションでは、レイアウトのサイドバーの内容をコンテンツに上書きするのではなく追加するために@@parent
ディレクティブを使用しています。@@parent
ディレクティブはビューをレンダーするときに、レイアウトの内容に置き換わります。
もちろん生のPHPビューと同様、Bladeビューはグローバルなview
ヘルパを使用し、ルートから返すことができます。
Route::get('blade', function () {
return view('child');
});
データ表示
Bladeビューに渡されたデータは、波括弧で変数を囲うことで表示できます。たとえば、次のルートがあるとしましょう。
Route::get('greeting', function () {
return view('welcome', ['name' => 'Samantha']);
});
name
変数の内容を表示しましょう。
Hello, {{ $name }}.
もちろんビューに渡された変数の内容を表示するだけに限られません。PHP関数の結果をechoすることもできます。実際、どんなPHPコードもBladeのecho文の中に書けます。
現在のUnixタイムスタンプは、{{ time() }}です。
注意: Bladeの
{{ }}
文は自動的にPHPのhtmlentities
関数を通し、XSS攻撃を防ぎます。
BladeとJavaScriptフレームワーク
多くのJavaScriptフレームワークでも、与えられた式をブラウザに表示するために波括弧を使っていますので、@
シンボルでBladeレンダリングエンジンに波括弧の展開をしないように指示することが可能です。
<h1>Laravel</h1>
Hello, @{{ name }}.
この例で、@
記号はBladeにより削除されます。しかし、{{ name }}
式はBladeエンジンにより変更されずにそのまま残り、JavaScriptフレームワークによりレンダリングできるようになります。
存在時のデータ表示
変数をechoしたいが、その変数がセットされているかわからない場合もあるでしょう。複雑なPHPコードを使えば可能です。
{{ isset($name) ? $name : 'Default' }}
しかし三項演算子の代わりに、Bladeは便利な次の短縮形を提供しています。
{{ $name or 'Default' }}
この例の場合、$name
変数が存在すれば値が表示されます。しかし存在していなければDefault
という言葉が表示されます。
エスケープしないデータの表示
デフォルトでブレードの{{ }}
文はXSS攻撃を防ぐために、PHPのhtmlentities
関数を自動的に通されます。しかしデータをエスケープしたくない場合は、以下の構文を使ってください。
Hello, {!! $name !!}.
注意: アプリケーションでユーザの入力内容をechoする場合は注意が必要です。コンテンツは常に二重の波括弧の記法でHTMLエンティティにエスケープすべきです。
制御構文
テンプレートの継承とデータ表示に付け加え、Bladeは条件文やループなどの一般的なPHPの制御構文の便利な短縮形を提供しています。こうした短縮形はPHP制御構文のきれいで簡潔な記述を提供しつつも、対応するPHPの構文とそっくりです。
If文
if
文の構文には、@if
、@elseif
、@else
、@endif
ディレクティブを使用します。これらの使い方はPHPの構文と同じです。
@if (count($records) === 1)
1レコードある!
@elseif (count($records) > 1)
複数レコードある!
@else
レコードがない!
@endif
便利なように、Bladeでは@unlessディレクティブも提供しています。
@unless (Auth::check())
あなたはログインしていません。
@endunless
@hasSection
ディレクティブを用いて、指定したレイアウトセクションに、コンテンツが存在するかを判定することもできます。
<title>
@hasSection ('title')
@yield('title') - App Name
@else
App Name
@endif
</title>
繰り返し
条件文に加え、BladeはPHPがサポートしている繰り返し構文も提供しています。これらも、対応するPHP構文と使い方は一緒です。
@for ($i = 0; $i < 10; $i++)
現在の値は: {{ $i }}
@endfor
@foreach ($users as $user)
<p>これは {{ $user->id }} ユーザです。</p>
@endforeach
@forelse ($users as $user)
<li>{{ $user->name }}</li>
@empty
<p>ユーザなし</p>
@endforelse
@while (true)
<p>無限ループ中</p>
@endwhile
繰り返しを使用する場合、ループを終了するか、現在の繰り返しをスキップすることもできます。
@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
サブビューの読み込み
Bladeの@include
ディレクディブを使えば、ビューの中から簡単に他のBladeビューを取り込めます。取り込み元のビューで使用可能な変数は、取り込み先のビューでも利用可能です。
<div>
@include('shared.errors')
<form>
<!-- フォームの内容 -->
</form>
</div>
親のビューの全データ変数が取り込み先のビューに継承されますが、追加のデータも配列で渡すことができます。
@include('view.name', ['some' => 'data'])
注意: Bladeビューの中では
__DIR__
や__FILE__
を使わないでください。キャッシュされたビューのパスが返されるからです。
コレクションのレンダービュー
Bladeの@each
ディレクティブを使い、ループとビューの読み込みを組み合わせられます。
@each('view.name', $jobs, 'job')
最初の引数は配列かコレクションの各要素をレンダーするための部分ビューです。第2引数は繰り返し処理する配列かコレクションで、第3引数はビューの中の繰り返し値が代入される変数名です。ですから、たとえばjobs
配列を繰り返す場合なら、部分ビューの中で各ジョブにはjob
変数としてアクセスしたいと通常は考えるでしょう。
現在の繰り返しのキーは、部分ビューの中のkey
変数で参照できます。
@each
ディレクティブには第4引数を渡たせます。この引数は配列が空の場合にレンダーされるビューを指定します。
@each('view.name', $jobs, 'job', 'view.empty')
コメント
Bladeでビューにコメントを書くこともできます。HTMLコメントと異なり、Bladeのコメントはアプリケーションから返されるHTMLには含まれません。
{{-- このコメントはレンダー後のHTMLには現れない --}}
スタック
Bladeはさらに、他のビューやレイアウトでレンダーできるように、名前付きのスタックへ内容を退避できます。
@push('scripts')
<script src="/example.js"></script>
@endpush
同じスタックを好きなだけ何度も引き出すことができます。スタックの内容をレンダーするには、@stack
ディレクティブを使います。
<head>
<!-- Headの内容 -->
@stack('scripts')
</head>
サービス注入
@inject
ディレクティブはLaravelのサービスコンテナからサービスを取得するために使用します。@inject
の最初の引数はそのサービスを取り込む変数名で、第2引数は依存解決したいクラス/インターフェイス名です。
@inject('metrics', 'App\Services\MetricsService')
<div>
Monthly Revenue: {{ $metrics->monthlyRevenue() }}.
</div>
Blade拡張
Bladeでは自分のカスタムディレクティブも定義することができます。directive
メソッドを使い、ディレクティブを登録します。Bladeコンパイラーがそのディレクティブを見つけると、引数に指定したコールバックが呼びだされます。
次の例は@datetime($var)
ディレクティブを作成し、渡された$var
をフォーマットします。
<?php
namespace App\Providers;
use Blade;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* サービスの初期起動後に登録する
*
* @return void
*/
public function boot()
{
Blade::directive('datetime', function($expression) {
return "<?php echo with{$expression}->format('m/d/Y H:i'); ?>";
});
}
/**
* コンテナへ結合を登録する
*
* @return void
*/
public function register()
{
//
}
}
ご覧の通り、このディレクティブではLaravelのwith
ヘルパ関数が使われています。with
ヘルパはシンプルに指定されたオブジェクト/値を返します。メソッドチェーンを行うのに便利です。このディレクティブにより最終的に生成されるコードは、次の通りです。
<?php echo with($var)->format('m/d/Y H:i'); ?>
Bladeディレクティブのロジックを更新した後に、Bladeビューのキャッシュを全部削除する必要があります。view:clear
Artisanコマンドで、キャッシュされているBladeビューを削除できます。