Laravel 5.4 Bladeテンプレート

イントロダクション

BladeはシンプルながらパワフルなLaravelのテンプレートエンジンです。他の人気のあるPHPテンプレートエンジンとは異なり、ビューの中にPHPを直接記述することを許しています。全BladeビューはPHPへコンパイルされ、変更があるまでキャッシュされます。つまりアプリケーションのオーバーヘッドは基本的に0です。Bladeビューには.blade.phpファイル拡張子を付け、通常はresources/viewsディレクトリの中に設置します。

テンプレートの継承

レイアウト定義

Bladeを使用する主な利点は、テンプレートの継承セクションです。初めに簡単な例を見てください。通常ほとんどのアプリケーションでは、数多くのページを同じ全体的なレイアウトの中に表示するので、最初は"master"ページレイアウトを確認しましょう。レイアウトは一つのBladeビューとして、簡単に定義できます。

<!-- resources/views/layouts/app.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.app')

@section('title', 'Page Title')

@section('sidebar')
    @@parent

    <p>ここはメインのサイドバーに追加される</p>
@endsection

@section('content')
    <p>ここが本文のコンテンツ</p>
@endsection

この例のsidebarセクションでは、レイアウトのサイドバーの内容をコンテンツに上書きするのではなく追加するために@@parentディレクティブを使用しています。@@parentディレクティブはビューをレンダーするときに、レイアウトの内容に置き換わります。

Bladeビューはグローバルなviewヘルパを使用し、ルートから返すことができます。

Route::get('blade', function () {
    return view('child');
});

コンポーネントとスロット

コンポーネントとスロットは、セクションとレイアウトと似た利便を提供します。しかし、コンポーネントとスロットのメンタルモデルのほうが簡単に理解できることに気づくはずです。最初に、アプリケーション全体で再利用する、"alert"コンポーネントをイメージしてください。

<!-- /resources/views/alert.blade.php -->

<div class="alert alert-danger">
    {{ $slot }}
</div>

{{ $slot }}変数は、このコンポーネントへ注入しようとする内容を含んでいます。では、このコンポーネントを構築するため、@component Bladeディレクティブを使いましょう。

@component('alert')
    <strong>Whoops!</strong> Something went wrong!
@endcomponent

一つのコンポーネントに対し、複数のスロットを定義するのも、役立つことがあるでしょう。"title"を注入できるようにalertコンポーネントを改造してみましょう。名前付きスロットは、名前に一致する変数をただ"echo"します。

<!-- /resources/views/alert.blade.php -->

<div class="alert alert-danger">
    <div class="alert-title">{{ $title }}</div>

    {{ $slot }}
</div>

これで、@slotディレクティブを使い、名前付きスロットへ内容を注入できます。@slotディレクティブ範囲外の全内容は、$slot変数の中のコンポーネントへ渡されます。

@component('alert')
    @slot('title')
        Forbidden
    @endslot

    You are not allowed to access this resource!
@endcomponent

コンポーネントへ追加のデータを渡す

場合により、コンポーネントへ追加のデータを渡す必要が起きます。そのため、@componentディレクティブの第2引数で、データの配列が渡せます。全データはテンプレート中で変数として利用できます。

@component('alert', ['foo' => 'bar'])
    ...
@endcomponent

データ表示

Bladeビューに渡されたデータは、波括弧で変数を囲うことで表示できます。たとえば、次のルートがあるとしましょう。

Route::get('greeting', function () {
    return view('welcome', ['name' => 'Samantha']);
});

name変数の内容を表示しましょう。

Hello, {{ $name }}.

もちろんビューに渡された変数の内容を表示するだけに限られません。PHP関数の結果をechoすることもできます。実際、どんなPHPコードもBladeのecho文の中に書けます。

The current UNIX timestamp is {{ time() }}.

Note: Bladeの{{ }}記法はXSS攻撃を防ぐため、自動的にPHPのhtmlspecialchars関数を通されます。

エスケープしないデータの表示

デフォルトでブレードの{{ }}文はXSS攻撃を防ぐために、PHPのhtmlspecialchars関数を自動的に通されます。しかしデータをエスケープしたくない場合は、以下の構文を使ってください。

Hello, {!! $name !!}.

Note: アプリケーションでユーザの入力内容をechoする場合は注意が必要です。ユーザの入力を表示するときは、常に二重の波括弧の記法でHTMLエンティティにエスケープすべきです。

BladeとJavaScriptフレームワーク

多くのJavaScriptフレームワークでも、与えられた式をブラウザに表示するために波括弧を使っていますので、@シンボルでBladeレンダリングエンジンに波括弧の展開をしないように指示することが可能です。

<h1>Laravel</h1>

Hello, @{{ name }}.

この例で、@記号はBladeにより削除されます。しかし、{{ name }}式はBladeエンジンにより変更されずにそのまま残り、JavaScriptフレームワークによりレンダリングできるようになります。

@verbatimディレクティブ

テンプレートの広い箇所でJavaScript変数を表示する場合は、HTMLを@verbatimディレクティブで囲めば、各Blade echo文の先頭に@記号を付ける必要はなくなります。

@verbatim
    <div class="container">
        Hello, {{ name }}.
    </div>
@endverbatim

制御構文

テンプレートの継承とデータ表示に付け加え、Bladeは条件文やループなどの一般的なPHPの制御構文の便利な短縮記述方法を提供しています。こうした短縮形は、PHP制御構文の美しく簡潔な記述を提供しつつも、対応するPHPの構文と似せています。

If文

if文の構文には、@if@elseif@else@endifディレクティブを使用します。これらの使い方はPHPの構文と同じです。

@if (count($records) === 1)
    1レコードある!
@elseif (count($records) > 1)
    複数レコードある!
@else
    レコードがない!
@endif

便利な@unlessディレクティブも提供しています。

@unless (Auth::check())
    あなたはログインしていません。
@endunless

さらに、既に説明したように@isset@emptyディレクティブも、同名のPHP関数の便利なショートカットとして使用できます。

@isset($records)
    // $recordsは定義済みでnullでない
@endisset

@empty($records)
    // $recordsが「空」だ
@endempty

繰り返し

条件文に加え、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

Tip!! 繰り返し中はループ変数を使い、繰り返しの最初や最後なのかなど、繰り返し情報を取得できます。

繰り返しを使用する場合、ループを終了するか、現在の繰り返しをスキップすることもできます。

@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

ループ変数

繰り返し中は、$loop変数が使用できます。この変数により、現在のループインデックスや繰り返しの最初/最後なのかなど、便利な情報にアクセスできます。

@foreach ($users as $user)
    @if ($loop->first)
        これは最初の繰り返し
    @endif

    @if ($loop->last)
        これは最後の繰り返し
    @endif

    <p>これは {{ $user->id }} ユーザです。</p>
@endforeach

ネストした繰り返しでは、親のループの$loop変数にparentプロパティを通じアクセスできます。

@foreach ($users as $user)
    @foreach ($user->posts as $post)
        @if ($loop->parent->first)
            これは親のループの最初の繰り返しだ
        @endif
    @endforeach
@endforeach

$loop変数は、他にもいろいろと便利なプロパティを持っています。

プロパティ 説明
$loop->index 現在のループのインデックス(初期値0)
$loop->iteration 現在の繰り返し数(初期値1)
$loop->remaining 繰り返しの残り数
$loop->count 繰り返し中の配列の総アイテム数
$loop->first ループの最初の繰り返しか
$loop->last ループの最後の繰り返しか
$loop->depth 現在のループのネストレベル
$loop->parent ループがネストしている場合、親のループ変数

コメント

Bladeでビューにコメントを書くこともできます。HTMLコメントと異なり、Bladeのコメントはアプリケーションから返されるHTMLには含まれません。

{{-- このコメントはレンダー後のHTMLには現れない --}}

PHP

PHPコードをビューへ埋め込むと便利な場合もあります。Bladeの@phpディレクティブを使えば、テンプレートの中でプレーンなPHPブロックを実行できます。

@php
    //
@endphp

Tip!! Bladeはこの機能を提供していますが、数多く使用しているのであれば、それはテンプレートへ多すぎるロジックを埋め込んでいるサインです。

サブビューの読み込み

Bladeの@includeディレクディブを使えば、ビューの中から簡単に他のBladeビューを取り込めます。読み込み元のビューで使用可能な変数は、取り込み先のビューでも利用可能です。

<div>
    @include('shared.errors')

    <form>
        <!-- フォームの内容 -->
    </form>
</div>

親のビューの全データ変数が取り込み先のビューに継承されますが、追加のデータも配列で渡すことができます。

@include('view.name', ['some' => 'data'])

もちろん、存在しないビューを@includeすれば、Laravelはエラーを投げます。存在しているかどうかわからないビューを取り込みたい場合は、@includeIfディレクティブを使います。

@includeIf('view.name', ['some' => 'data'])

指定した論理条件にもとづいて@includeしたい場合は、@includeWhenディレクティブを使用します。

@includeWhen($boolean, 'view.name', ['some' => 'data'])

Note: 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はさらに、他のビューやレイアウトでレンダーできるように、名前付きのスタックへ内容を退避できます。子ビューで必要なJavaScriptを指定する場合に、便利です。

@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)ディレクティブを作成し、渡されるDateTimeインスタンスの$varをフォーマットします。

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * サービスの初期起動後に登録する
     *
     * @return void
     */
    public function boot()
    {
        Blade::directive('datetime', function ($expression) {
            return "<?php echo ($expression)->format('m/d/Y H:i'); ?>";
        });
    }

    /**
     * コンテナへ結合を登録する
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

ご覧の通り、ディレクティブがどんなものであれ、渡された引数にformatメソッドをチェーンし、呼び出しています。そのため、この例のディレクティブの場合、最終的に生成されるPHPコードは、次のようになります。

<?php echo ($var)->format('m/d/Y H:i'); ?>

Note: Bladeディレクティブのロジックを更新した後に、Bladeビューのキャッシュを全部削除する必要があります。view:clear Artisanコマンドで、キャッシュされているBladeビューを削除できます。

ドキュメント章別ページ

公式パッケージ

ヘッダー項目移動

注目:アイコン:ページ内リンク設置(リンクがないヘッダーへの移動では、リンクがある以前のヘッダーのハッシュをURLへ付加します。

移動

クリックで即時移動します。

バージョン

設定

適用ボタンクリック後に、全項目まとめて適用されます。

カラーテーマ
和文指定 Pagination
和文指定 Scaffold
Largeスクリーン表示幅
インデント
本文フォント
コードフォント
フォント適用確認

フォントの指定フィールドから、フォーカスが外れると、当ブロックの内容に反映されます。EnglishのDisplayもPreviewしてください。

フォント設定時、表示に不具合が出た場合、当サイトのクッキーを削除してください。

バックスラッシュを含むインライン\Code\Blockの例です。

以下はコードブロックの例です。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * ユーザに関連する電話レコードを取得
     */
    public function phone()
    {
        return $this->hasOne('App\Phone');
    }
}

設定を保存する前に、表示が乱れないか必ず確認してください。CSSによるフォントファミリー指定の知識がない場合は、フォントを変更しないほうが良いでしょう。

キーボード・ショートカット

オープン操作

PDC

ページ(章)移動の左オフキャンバスオープン

HA

ヘッダー移動モーダルオープン

MS

移動/設定の右オフキャンバスオープン

ヘッダー移動

T

最初のヘッダーへ移動

E

最後のヘッダーへ移動

NJ

次ヘッダー(H2〜H4)へ移動

BK

前ヘッダー(H2〜H4)へ移動

その他

?

このヘルプページ表示
閉じる