メインコンテンツまでスキップ

Blade テンプレート

はじめに

Bladeは、Laravelに含まれるシンプルでありながら強力なテンプレートエンジンです。一部のPHPテンプレートエンジンとは異なり、Bladeではテンプレート内でプレーンなPHPコードを使用する制限がありません。実際、すべてのBladeテンプレートはプレーンなPHPコードにコンパイルされ、変更されるまでキャッシュされます。つまり、Bladeはアプリケーションにほとんどオーバーヘッドを追加しません。Bladeテンプレートファイルは.blade.php拡張子を使用し、通常はresources/viewsディレクトリに保存されます。

Bladeビューは、グローバルなviewヘルパーを使用して、ルートまたはコントローラから返すことができます。もちろん、ビューのドキュメントで説明されているように、データはviewヘルパーの第2引数を使用してBladeビューに渡すことができます。

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

Laravel LivewireでBladeを強化する

Bladeテンプレートを次のレベルに引き上げて、簡単に動的なインターフェースを構築したいですか?Laravel Livewireをチェックしてみてください。Livewireを使用すると、通常はReactやVueなどのフロントエンドフレームワークでのみ可能な動的機能が追加されたBladeコンポーネントを記述できます。これにより、多くのJavaScriptフレームワークの複雑さ、クライアントサイドのレンダリング、ビルドステップなしで、モダンで反応性のあるフロントエンドを構築するための素晴らしいアプローチが提供されます。

データの表示

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

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

name変数の内容を次のように表示できます:

Hello, {{ $name }}.
注記

Bladeの{{ }}エコーステートメントは、XSS攻撃を防ぐために自動的にPHPのhtmlspecialchars関数を通過します。

ビューに渡された変数の内容を表示することに制限されることはありません。PHP関数の結果をエコーすることもできます。実際、Bladeエコーステートメント内には任意のPHPコードを配置できます。

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

HTML エンティティのエンコーディング

デフォルトでは、Blade(およびLaravelの e 関数)はHTMLエンティティを二重にエンコードします。二重エンコードを無効にしたい場合は、AppServiceProviderboot メソッドから Blade::withoutDoubleEncoding メソッドを呼び出してください:

    <?php

namespace App\Providers;

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

class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Blade::withoutDoubleEncoding();
}
}

エスケープされていないデータの表示

デフォルトでは、Bladeの {{ }} ステートメントは自動的にPHPの htmlspecialchars 関数を通過してXSS攻撃を防ぎます。データをエスケープしたくない場合は、次の構文を使用できます:

Hello, {!! $name !!}.
警告

アプリケーションのユーザーから提供されたコンテンツをエコーする際は非常に注意してください。ユーザーが提供したデータを表示する際にXSS攻撃を防ぐために通常はエスケープされた、二重中括弧の構文を使用するべきです。

Blade と JavaScript フレームワーク

多くのJavaScriptフレームワークもブラウザに表示されるべき表現を示すために「中括弧」を使用するため、Bladeレンダリングエンジンに表現がそのまま残るようにするために @ 記号を使用できます。例:

<h1>Laravel</h1>

Hello, @{{ name }}.

この例では、@ 記号はBladeによって削除されますが、{{ name }} 表現はBladeエンジンによってそのまま残され、JavaScriptフレームワークによってレンダリングされることが可能になります。

@ 記号はBladeディレクティブをエスケープするためにも使用できます:

{{-- Blade template --}}
@@if()

<!-- HTML output -->
@if()

JSON のレンダリング

時々、JavaScript変数を初期化するためにJSONとしてレンダリングする意図でビューに配列を渡すことがあります。例:

<script>
var app = <?php echo json_encode($array); ?>;
</script>

ただし、json_encode を手動で呼び出す代わりに、Illuminate\Support\Js::from メソッドディレクティブを使用することができます。from メソッドはPHPの json_encode 関数と同じ引数を受け入れますが、結果のJSONがHTMLの引用符内に適切にエスケープされることを保証します。from メソッドは、指定されたオブジェクトや配列を有効なJavaScriptオブジェクトに変換する JSON.parse JavaScriptステートメントの文字列を返します:

最新のLaravelアプリケーションスケルトンには、Bladeテンプレート内でこの機能に便利にアクセスできるJsファサードが含まれています:

<script>
var app = {{ Js::from($array) }};
</script>
警告

既存の変数をJSONとしてレンダリングする場合は、Js::fromメソッドのみを使用する必要があります。Bladeテンプレートは正規表現に基づいており、複雑な式をディレクティブに渡すと予期しない失敗が発生する可能性があります。

@verbatimディレクティブ

テンプレートの大部分でJavaScript変数を表示する場合は、各Bladeエコーステートメントに@記号を付ける必要がないように、HTMLを@verbatimディレクティブでラップすることができます:

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

Bladeディレクティブ

テンプレートの継承とデータ表示に加えて、Bladeは条件文やループなどの一般的なPHP制御構造の便利なショートカットも提供しています。これらのショートカットは、PHPの制御構造と非常に似ているが、非常にクリーンで簡潔な方法でPHPの制御構造を扱うことができます。

If文

@if@elseif@else@endifディレクティブを使用してif文を構築することができます。これらのディレクティブは、PHPの対応物と同じように機能します:

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

便宜上、Bladeは@unlessディレクティブも提供しています:

@unless (Auth::check())
You are not signed in.
@endunless

すでに議論されている条件ディレクティブに加えて、@issetおよび@emptyディレクティブは、それぞれのPHP関数の便利なショートカットとして使用できます:

@isset($records)
// $records is defined and is not null...
@endisset

@empty($records)
// $records is "empty"...
@endempty

認証ディレクティブ

@authおよび@guestディレクティブを使用して、現在のユーザーが認証されているかどうか、またはゲストかどうかを迅速に判断することができます:

@auth
// The user is authenticated...
@endauth

@guest
// The user is not authenticated...
@endguest

必要に応じて、@authおよび@guestディレクティブを使用する際にチェックすべき認証ガードを指定することができます。

@auth('admin')
// The user is authenticated...
@endauth

@guest('admin')
// The user is not authenticated...
@endguest

環境ディレクティブ

@production ディレクティブを使用して、アプリケーションが本番環境で実行されているかどうかを確認できます:

@production
// Production specific content...
@endproduction

または、@env ディレクティブを使用して、アプリケーションが特定の環境で実行されているかどうかを判断できます:

@env('staging')
// The application is running in "staging"...
@endenv

@env(['staging', 'production'])
// The application is running in "staging" or "production"...
@endenv

セクションディレクティブ

@hasSection ディレクティブを使用して、テンプレート継承セクションにコンテンツがあるかどうかを判断できます:

@hasSection('navigation')
<div class="pull-right">
@yield('navigation')
</div>

<div class="clearfix"></div>
@endif

セクションにコンテンツがないかどうかを判断するには、sectionMissing ディレクティブを使用できます:

@sectionMissing('navigation')
<div class="pull-right">
@include('default-navigation')
</div>
@endif

セッションディレクティブ

@session ディレクティブを使用して、セッション 値が存在するかどうかを判断できます。セッション値が存在する場合、@session および @endsession ディレクティブ内のテンプレートコンテンツが評価されます。@session ディレクティブのコンテンツ内では、$value 変数をエコーしてセッション値を表示できます:

@session('status')
<div class="p-4 bg-green-100">
{{ $value }}
</div>
@endsession

スイッチ文

@switch@case@break@default@endswitch ディレクティブを使用して、スイッチ文を構築できます:

@switch($i)
@case(1)
First case...
@break

@case(2)
Second case...
@break

@default
Default case...
@endswitch

ループ

条件文に加えて、Blade は PHP のループ構造を扱うためのシンプルなディレクティブを提供します。これらのディレクティブは、それぞれ PHP の対応するものと同じように機能します:

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

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

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

@while (true)
<p>I'm looping forever.</p>
@endwhile
注記

foreach ループを繰り返す際に、ループ変数 を使用して、ループ内で最初か最後の反復かなど、ループに関する貴重な情報を取得できます。

ループを使用する際に、@continue および @break ディレクティブを使用して、現在の反復をスキップしたり、ループを終了したりできます:

@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

ループ変数

foreach ループを繰り返す際、ループ内で $loop 変数が利用可能になります。この変数には、現在のループインデックスや、これが最初のイテレーションか最後のイテレーションかなど、便利な情報にアクセスできます:

@foreach ($users as $user)
@if ($loop->first)
This is the first iteration.
@endif

@if ($loop->last)
This is the last iteration.
@endif

<p>This is user {{ $user->id }}</p>
@endforeach

ネストされたループ内である場合、parent プロパティを使用して親ループの $loop 変数にアクセスできます:

@foreach ($users as $user)
@foreach ($user->posts as $post)
@if ($loop->parent->first)
This is the first iteration of the parent loop.
@endif
@endforeach
@endforeach

$loop 変数には、他にもさまざまな便利なプロパティが含まれています:

プロパティ説明
$loop->index現在のループイテレーションのインデックス(0 から開始)。
$loop->iteration現在のループイテレーション(1 から開始)。
$loop->remainingループ内の残りのイテレーション数。
$loop->countイテレートされている配列内のアイテムの総数。
$loop->firstこれがループ内の最初のイテレーションかどうか。
$loop->lastこれがループ内の最後のイテレーションかどうか。
$loop->evenこれが偶数のイテレーションかどうか。
$loop->oddこれが奇数のイテレーションかどうか。
$loop->depth現在のループのネストレベル。
$loop->parentネストされたループ内である場合、親のループ変数。

条件付きクラスとスタイル

@class ディレクティブは、CSS クラス文字列を条件付きでコンパイルします。このディレクティブは、クラスを追加したいクラスまたはクラスを含む配列を受け入れます。配列のキーには追加したいクラスが含まれ、値はブール式です。配列要素のキーが数値である場合、常にレンダリングされるクラスリストに含まれます:

@php
$isActive = false;
$hasError = true;
@endphp

<span @class([
'p-4',
'font-bold' => $isActive,
'text-gray-500' => ! $isActive,
'bg-red' => $hasError,
])></span>

<span class="p-4 text-gray-500 bg-red"></span>

同様に、@style ディレクティブを使用して、HTML 要素にインライン CSS スタイルを条件付きで追加することができます。

@php
$isActive = true;
@endphp

<span @style([
'background-color: red',
'font-weight: bold' => $isActive,
])></span>

<span style="background-color: red; font-weight: bold;"></span>

追加の属性

便宜上、@checkedディレクティブを使用して、指定されたHTMLチェックボックス入力が「チェックされている」かどうかを簡単に示すことができます。このディレクティブは、提供された条件がtrueに評価される場合にcheckedをエコーします:

<input type="checkbox"
name="active"
value="active"
@checked(old('active', $user->active)) />

同様に、@selectedディレクティブは、指定された選択オプションが「選択されている」かどうかを示すために使用できます:

<select name="version">
@foreach ($product->versions as $version)
<option value="{{ $version }}" @selected(old('version') == $version)>
{{ $version }}
</option>
@endforeach
</select>

さらに、@disabledディレクティブは、指定された要素が「無効」であるかどうかを示すために使用できます:

<button type="submit" @disabled($errors->isNotEmpty())>Submit</button>

さらに、@readonlyディレクティブは、指定された要素が「読み取り専用」であるかどうかを示すために使用できます:

<input type="email"
name="email"
value="email@laravel.com"
@readonly($user->isNotAdmin()) />

さらに、@requiredディレクティブは、指定された要素が「必須」であるかどうかを示すために使用できます:

<input type="text"
name="title"
value="title"
@required($user->isAdmin()) />

サブビューのインクルード

注記

@includeディレクティブを使用することは自由ですが、Bladeのコンポーネントは、データや属性のバインディングなど、@includeディレクティブよりもいくつかの利点を提供します。

Bladeの@includeディレクティブを使用すると、別のビュー内からBladeビューをインクルードできます。親ビューで利用可能なすべての変数は、インクルードされたビューで利用可能になります:

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

<form>
<!-- Form Contents -->
</form>
</div>

インクルードされたビューは親ビューで利用可能なすべてのデータを継承しますが、インクルードされたビューで利用可能にする追加のデータの配列も渡すことができます:

@include('view.name', ['status' => 'complete'])

存在しないビューを@includeしようとすると、Laravelはエラーをスローします。存在するかどうかわからないビューをインクルードしたい場合は、@includeIfディレクティブを使用する必要があります:

@includeIf('view.name', ['status' => 'complete'])

特定のブール式がtrueまたはfalseに評価される場合にビューを@includeしたい場合は、@includeWhenおよび@includeUnlessディレクティブを使用できます:

@includeWhen($boolean, 'view.name', ['status' => 'complete'])

@includeUnless($boolean, 'view.name', ['status' => 'complete'])

指定されたビューの配列から最初に存在するビューを含めるには、includeFirst ディレクティブを使用できます:

@includeFirst(['custom.admin', 'admin'], ['status' => 'complete'])
警告

Blade ビューで __DIR____FILE__ 定数を使用するのは避けるべきです。これらはキャッシュされたコンパイルされたビューの場所を参照します。

コレクションのためのビューのレンダリング

Blade の @each ディレクティブを使用して、ループとインクルードを1行に組み合わせることができます:

@each('view.name', $jobs, 'job')

@each ディレクティブの最初の引数は、配列またはコレクション内の各要素に対してレンダリングするビューです。2 番目の引数は、繰り返し処理する配列またはコレクションであり、3 番目の引数はビュー内で現在の繰り返しに割り当てられる変数名です。たとえば、jobs の配列を繰り返し処理している場合、通常はビュー内で job 変数として各ジョブにアクセスしたいと思うでしょう。現在の繰り返しの配列キーは、ビュー内で key 変数として利用可能です。

@each ディレクティブには 4 番目の引数を渡すこともできます。この引数は、指定された配列が空の場合にレンダリングされるビューを決定します。

@each('view.name', $jobs, 'job', 'view.empty')
警告

@each を介してレンダリングされるビューは、親ビューから変数を継承しません。子ビューがこれらの変数を必要とする場合は、代わりに @foreach および @include ディレクティブを使用する必要があります。

@once ディレクティブ

@once ディレクティブを使用すると、テンプレートの一部をレンダリングサイクルごとに 1 回だけ評価できます。これは、stacks を使用してページのヘッダーに特定の JavaScript ピースをプッシュする場合に便利です。たとえば、ループ内で特定の component をレンダリングしている場合、コンポーネントが最初にレンダリングされるときだけ JavaScript をヘッダーにプッシュしたい場合があります:

@once
@push('scripts')
<script>
// Your custom JavaScript...
</script>
@endpush
@endonce

@once ディレクティブはしばしば @push または @prepend ディレクティブと組み合わせて使用されるため、便宜上 @pushOnce および @prependOnce ディレクティブが利用可能です。

@pushOnce('scripts')
<script>
// Your custom JavaScript...
</script>
@endPushOnce

Raw PHP

いくつかの状況では、ビューに PHP コードを埋め込むことが役立ちます。Blade の @php ディレクティブを使用して、テンプレート内でプレーンな PHP ブロックを実行できます:

@php
$counter = 1;
@endphp

または、クラスをインポートするだけの場合は、@use ディレクティブを使用できます:

@use('App\Models\Flight')

インポートされたクラスにエイリアスを付けるために、@use ディレクティブに第二引数を指定することもできます:

@use('App\Models\Flight', 'FlightModel')

Comments

Blade では、ビュー内でコメントを定義することもできます。ただし、HTML コメントとは異なり、Blade コメントはアプリケーションが返す HTML には含まれません:

{{-- This comment will not be present in the rendered HTML --}}

Components

コンポーネントとスロットは、セクション、レイアウト、およびインクルードと同様の利点を提供しますが、コンポーネントとスロットのメンタルモデルが理解しやすいと感じる人もいます。コンポーネントを記述する方法には、クラスベースのコンポーネントと匿名コンポーネントの2つのアプローチがあります。

クラスベースのコンポーネントを作成するには、make:component Artisan コマンドを使用できます。コンポーネントの使用方法を説明するために、シンプルな Alert コンポーネントを作成します。make:component コマンドは、コンポーネントを app/View/Components ディレクトリに配置します:

php artisan make:component Alert

make:component コマンドは、コンポーネントのビューテンプレートも作成します。このビューは resources/views/components ディレクトリに配置されます。独自のアプリケーション用のコンポーネントを記述する場合、コンポーネントは通常、app/View/Components ディレクトリと resources/views/components ディレクトリ内で自動的に検出されるため、通常は追加のコンポーネント登録は必要ありません。

サブディレクトリ内にコンポーネントを作成することもできます:

php artisan make:component Forms/Input

上記のコマンドは、app/View/Components/Forms ディレクトリに Input コンポーネントを作成し、ビューは resources/views/components/forms ディレクトリに配置されます。

匿名コンポーネント(Blade テンプレートのみでクラスがないコンポーネント)を作成したい場合は、make:component コマンドを呼び出す際に --view フラグを使用できます:

php artisan make:component forms.input --view

上記のコマンドは、resources/views/components/forms/input.blade.php に Blade ファイルを作成し、<x-forms.input /> を使用してコンポーネントとしてレンダリングできます。

パッケージコンポーネントの手動登録

独自のアプリケーション用のコンポーネントを作成する場合、コンポーネントは app/View/Components ディレクトリと resources/views/components ディレクトリ内で自動的に検出されます。

ただし、Blade コンポーネントを利用するパッケージを構築している場合は、コンポーネントクラスとその HTML タグのエイリアスを手動で登録する必要があります。通常、パッケージのサービスプロバイダの boot メソッドでコンポーネントを登録する必要があります:

    use Illuminate\Support\Facades\Blade;

/**
* Bootstrap your package's services.
*/
public function boot(): void
{
Blade::component('package-alert', Alert::class);
}

コンポーネントが登録されたら、そのタグエイリアスを使用してレンダリングできます:

<x-package-alert/>

また、componentNamespace メソッドを使用して、コンポーネントクラスを規約に従って自動的に読み込むこともできます。たとえば、Nightshade パッケージには Package\Views\Components ネームスペース内に存在する CalendarColorPicker コンポーネントがあるとします:

    use Illuminate\Support\Facades\Blade;

/**
* Bootstrap your package's services.
*/
public function boot(): void
{
Blade::componentNamespace('Nightshade\\Views\\Components', 'nightshade');
}

これにより、package-name:: 構文を使用してベンダーネームスペースでパッケージコンポーネントを使用できます:

<x-nightshade::calendar />
<x-nightshade::color-picker />

Blade は、このコンポーネントにリンクされたクラスをパスカルケースで検出します。サブディレクトリも「ドット」表記を使用してサポートされています。

コンポーネントのレンダリング

コンポーネントを表示するには、Blade テンプレートの中で Blade コンポーネントタグを使用できます。Blade コンポーネントタグは、コンポーネントクラスの kebab case 名の後に x- という文字列で始まります:

<x-alert/>

<x-user-profile/>

コンポーネントクラスが app/View/Components ディレクトリ内でより深い階層にネストされている場合、. 文字を使用してディレクトリのネストを示すことができます。たとえば、コンポーネントが app/View/Components/Inputs/Button.php にあると仮定すると、次のようにレンダリングできます:

<x-inputs.button/>

コンポーネントを条件付きでレンダリングしたい場合は、コンポーネントクラスに shouldRender メソッドを定義することができます。shouldRender メソッドが false を返すと、コンポーネントはレンダリングされません:

    use Illuminate\Support\Str;

/**
* Whether the component should be rendered
*/
public function shouldRender(): bool
{
return Str::length($this->message) > 0;
}

コンポーネントへのデータの渡し方

Blade コンポーネントにデータを渡すには、HTML 属性を使用します。ハードコードされたプリミティブ値は、単純な HTML 属性文字列を使用してコンポーネントに渡すことができます。PHP の式や変数は、プレフィックスとして : 文字を使用する属性を介してコンポーネントに渡すべきです:

<x-alert type="error" :message="$message"/>

コンポーネントのデータ属性は、クラスのコンストラクタで定義するべきです。コンポーネントの公開プロパティは、自動的にコンポーネントのビューで利用可能になります。データをコンポーネントの render メソッドからビューに渡す必要はありません:

    <?php

namespace App\View\Components;

use Illuminate\View\Component;
use Illuminate\View\View;

class Alert extends Component
{
/**
* Create the component instance.
*/
public function __construct(
public string $type,
public string $message,
) {}

/**
* Get the view / contents that represent the component.
*/
public function render(): View
{
return view('components.alert');
}
}

コンポーネントをレンダリングする際には、コンポーネントの公開変数の内容を変数名でエコーすることで表示することができます:

<div class="alert alert-{{ $type }}">
{{ $message }}
</div>

ケース

コンポーネントのコンストラクタ引数は camelCase を使用して指定すべきですが、HTML 属性で引数名を参照する際には kebab-case を使用すべきです。たとえば、次のようなコンポーネントコンストラクタがある場合:

    /**
* Create the component instance.
*/
public function __construct(
public string $alertType,
) {}

$alertType 引数は、次のようにコンポーネントに提供できます:

<x-alert alert-type="danger" />

短い属性構文

コンポーネントに属性を渡す際には、"短い属性" 構文も使用できます。これは、属性名が対応する変数名と一致することが多いため、便利です:

{{-- Short attribute syntax... --}}
<x-profile :$userId :$name />

{{-- Is equivalent to... --}}
<x-profile :user-id="$userId" :name="$name" />

属性のエスケープレンダリング

一部の JavaScript フレームワーク(Alpine.js など)もコロンをプレフィックスとする属性を使用するため、Blade にその属性が PHP の式でないことを伝えるために、ダブルコロン (::) プレフィックスを使用することができます。たとえば、次のようなコンポーネントがある場合:

<x-button ::class="{ danger: isDeleting }">
Submit
</x-button>

Bladeによって次のHTMLがレンダリングされます:

<button :class="{ danger: isDeleting }">
Submit
</button>

コンポーネントメソッド

コンポーネントテンプレートで公開変数が利用可能であるだけでなく、コンポーネントの公開メソッドも呼び出すことができます。たとえば、isSelectedメソッドを持つコンポーネントを想像してください:

    /**
* Determine if the given option is the currently selected option.
*/
public function isSelected(string $option): bool
{
return $option === $this->selected;
}

このメソッドは、コンポーネントテンプレートから、メソッド名と一致する変数を呼び出すことで実行できます:

<option {{ $isSelected($value) ? 'selected' : '' }} value="{{ $value }}">
{{ $label }}
</option>

コンポーネントクラス内での属性とスロットのアクセス

Bladeコンポーネントでは、クラスのrenderメソッド内でコンポーネント名、属性、およびスロットにアクセスすることもできます。ただし、このデータにアクセスするためには、コンポーネントのrenderメソッドからクロージャを返す必要があります。このクロージャは、唯一の引数として$data配列を受け取ります。この配列には、コンポーネントに関する情報を提供するいくつかの要素が含まれています:

    use Closure;

/**
* Get the view / contents that represent the component.
*/
public function render(): Closure
{
return function (array $data) {
// $data['componentName'];
// $data['attributes'];
// $data['slot'];

return '<div>Components content</div>';
};
}

componentNameは、x-プレフィックスの後にHTMLタグで使用された名前と等しいです。したがって、<x-alert />componentNamealertになります。attributes要素には、HTMLタグに存在したすべての属性が含まれます。slot要素は、コンポーネントのスロットの内容を持つIlluminate\Support\HtmlStringインスタンスです。

クロージャは文字列を返す必要があります。返された文字列が既存のビューに対応する場合、そのビューがレンダリングされます。それ以外の場合、返された文字列はインラインBladeビューとして評価されます。

追加の依存関係

コンポーネントがLaravelのサービスコンテナから依存関係を必要とする場合、コンポーネントのデータ属性の前にそれらをリストアップすることができます。これにより、コンテナによって自動的にインジェクションされます:

use App\Services\AlertCreator;

/**
* Create the component instance.
*/
public function __construct(
public AlertCreator $creator,
public string $type,
public string $message,
) {}

属性/メソッドの非表示

公開されるべきでない一部のメソッドやプロパティを、コンポーネントテンプレートに変数として公開しないようにしたい場合は、コンポーネントの$except配列プロパティにそれらを追加することができます:

    <?php

namespace App\View\Components;

use Illuminate\View\Component;

class Alert extends Component
{
/**
* The properties / methods that should not be exposed to the component template.
*
* @var array
*/
protected $except = ['type'];

/**
* Create the component instance.
*/
public function __construct(
public string $type,
) {}
}

コンポーネント属性

コンポーネントにデータ属性を渡す方法を既に見てきましたが、時にはclassなどの追加のHTML属性を指定する必要があることがあります。これらは、コンポーネントの機能に必要なデータの一部ではない属性を指定することが一般的です。例えば、次のようにalertコンポーネントをレンダリングしたいとします:

<x-alert type="error" :message="$message" class="mt-4"/>

コンポーネントのコンストラクタの一部でない属性は、自動的にコンポーネントの「属性バッグ」に追加されます。この属性バッグは、コンポーネント内で$attributes変数を介して自動的に利用可能になります。これらの属性は、コンポーネント内でこの変数をエコーすることですべてレンダリングできます:

<div {{ $attributes }}>
<!-- Component content -->
</div>
警告

@envなどのディレクティブをコンポーネントタグ内で使用することは現時点ではサポートされていません。例えば、<x-alert :live="@env('production')"/>はコンパイルされません。

デフォルト / マージされた属性

時には、属性のデフォルト値を指定したり、コンポーネントの一部の属性に追加の値をマージしたりする必要があることがあります。これを実現するために、属性バッグのmergeメソッドを使用できます。このメソッドは、常に適用されるべき一連のデフォルトCSSクラスを定義するのに特に便利です:

<div {{ $attributes->merge(['class' => 'alert alert-'.$type]) }}>
{{ $message }}
</div>

このコンポーネントが次のように利用されると仮定すると:

<x-alert type="error" :message="$message" class="mb-4"/>

コンポーネントの最終的なレンダリングされたHTMLは、次のように表示されます:

<div class="alert alert-error mb-4">
<!-- Contents of the $message variable -->
</div>

条件付きクラスのマージ

特定の条件がtrueの場合にクラスをマージしたい場合があります。これは、classメソッドを介して行うことができます。このメソッドは、クラスを追加したいクラスの配列を受け入れます。配列のキーには追加したいクラスが含まれ、値にはブール式が含まれます。配列要素のキーが数値である場合、常にレンダリングされるクラスリストに含まれます:

<div {{ $attributes->class(['p-4', 'bg-red' => $hasError]) }}>
{{ $message }}
</div>

他の属性をコンポーネントにマージする必要がある場合は、classメソッドにmergeメソッドをチェーンすることができます:

<button {{ $attributes->class(['p-4'])->merge(['type' => 'button']) }}>
{{ $slot }}
</button>
注記

他のHTML要素に条件付きでクラスをコンパイルする必要がある場合は、@classディレクティブを使用できます。

クラス以外の属性のマージ

class属性でない属性をマージする場合、mergeメソッドに提供される値は属性の「デフォルト」値と見なされます。ただし、class属性とは異なり、これらの属性は注入された属性値とマージされません。代わりに上書きされます。たとえば、buttonコンポーネントの実装は次のようになります:

<button {{ $attributes->merge(['type' => 'button']) }}>
{{ $slot }}
</button>

ボタンコンポーネントをカスタムのtypeでレンダリングするには、コンポーネントを使用する際に指定することができます。タイプが指定されていない場合は、buttonタイプが使用されます:

<x-button type="submit">
Submit
</x-button>

この例のbuttonコンポーネントのレンダリングされたHTMLは次のようになります:

<button type="submit">
Submit
</button>

class以外の属性がデフォルト値と注入された値が結合されるようにしたい場合は、prependsメソッドを使用できます。この例では、data-controller属性は常にprofile-controllerで始まり、追加の注入されたdata-controller値はこのデフォルト値の後に配置されます:

<div {{ $attributes->merge(['data-controller' => $attributes->prepends('profile-controller')]) }}>
{{ $slot }}
</div>

属性の取得とフィルタリング

filterメソッドを使用して属性をフィルタリングできます。このメソッドは、属性バッグ内の属性を保持する場合はtrueを返すクロージャを受け入れます:

{{ $attributes->filter(fn (string $value, string $key) => $key == 'foo') }}

便宜上、whereStartsWithメソッドを使用して、キーが特定の文字列で始まるすべての属性を取得できます:

{{ $attributes->whereStartsWith('wire:model') }}

逆に、whereDoesntStartWithメソッドを使用して、特定の文字列で始まるすべての属性を除外できます:

{{ $attributes->whereDoesntStartWith('wire:model') }}

first メソッドを使用すると、指定された属性バッグ内の最初の属性をレンダリングできます:

{{ $attributes->whereStartsWith('wire:model')->first() }}

コンポーネントに属性が存在するかどうかを確認したい場合は、has メソッドを使用できます。このメソッドは、属性名を唯一の引数として受け入れ、属性が存在するかどうかを示すブール値を返します:

@if ($attributes->has('class'))
<div>Class attribute is present</div>
@endif

has メソッドに配列が渡されると、メソッドは指定されたすべての属性がコンポーネントに存在するかどうかを判断します:

@if ($attributes->has(['name', 'class']))
<div>All of the attributes are present</div>
@endif

hasAny メソッドを使用すると、指定された属性のいずれかがコンポーネントに存在するかどうかを判断できます:

@if ($attributes->hasAny(['href', ':href', 'v-bind:href']))
<div>One of the attributes is present</div>
@endif

get メソッドを使用して特定の属性の値を取得できます:

{{ $attributes->get('class') }}

予約キーワード

デフォルトでは、Blade の内部でコンポーネントをレンダリングするために一部のキーワードが予約されています。次のキーワードは、コンポーネント内で公開プロパティやメソッド名として定義できません:

  • data
  • render
  • resolveView
  • shouldRender
  • view
  • withAttributes
  • withName

スロット

コンポーネントに追加のコンテンツを "スロット" を介して渡す必要があることがよくあります。コンポーネントのスロットは、$slot 変数をエコーすることでレンダリングされます。この概念を探るために、alert コンポーネントが次のマークアップを持つと想像してみましょう:

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

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

コンポーネントにコンテンツを注入することで、slot にコンテンツを渡すことができます:

<x-alert>
<strong>Whoops!</strong> Something went wrong!
</x-alert>

時には、コンポーネントが異なる場所で複数の異なるスロットをレンダリングする必要があるかもしれません。title スロットの挿入を許可するために、alert コンポーネントを変更してみましょう:

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

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

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

名前付きスロットのコンテンツは x-slot タグを使用して定義できます。明示的な x-slot タグ内にないコンテンツは、$slot 変数にコンポーネントに渡されます:

<x-alert>
<x-slot:title>
Server Error
</x-slot>

<strong>Whoops!</strong> Something went wrong!
</x-alert>

スロットにコンテンツが含まれているかどうかを判断するために、スロットの isEmpty メソッドを呼び出すことができます:

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

<div class="alert alert-danger">
@if ($slot->isEmpty())
This is default content if the slot is empty.
@else
{{ $slot }}
@endif
</div>

さらに、スロットに HTML コメント以外の "実際の" コンテンツが含まれているかどうかを判断するために、 hasActualContent メソッドを使用することができます:

@if ($slot->hasActualContent())
The scope has non-comment content.
@endif

スコープ付きスロット

Vue などの JavaScript フレームワークを使用したことがある場合、"スコープ付きスロット" についてはおそらくおなじみでしょう。これにより、スロット内でコンポーネントからデータやメソッドにアクセスできます。Laravel でも、コンポーネントでパブリックメソッドやプロパティを定義し、スロット内で $component 変数を介してコンポーネントにアクセスすることで同様の動作を実現できます。この例では、x-alert コンポーネントがそのコンポーネントクラスでパブリック formatAlert メソッドを定義していると仮定します:

<x-alert>
<x-slot:title>
{{ $component->formatAlert('Server Error') }}
</x-slot>

<strong>Whoops!</strong> Something went wrong!
</x-alert>

スロット属性

Blade コンポーネントと同様に、スロットに追加の 属性 を割り当てることができます:

<x-card class="shadow-sm">
<x-slot:heading class="font-bold">
Heading
</x-slot>

Content

<x-slot:footer class="text-sm">
Footer
</x-slot>
</x-card>

スロット属性とのやり取りについては、スロットの変数の attributes プロパティにアクセスすることができます。属性とのやり取りについての詳細は、component attributes のドキュメントを参照してください:

@props([
'heading',
'footer',
])

<div {{ $attributes->class(['border']) }}>
<h1 {{ $heading->attributes->class(['text-lg']) }}>
{{ $heading }}
</h1>

{{ $slot }}

<footer {{ $footer->attributes->class(['text-gray-700']) }}>
{{ $footer }}
</footer>
</div>

インラインコンポーネントビュー

非常に小さなコンポーネントの場合、コンポーネントクラスとコンポーネントのビューテンプレートの両方を管理するのは煩雑に感じるかもしれません。そのため、render メソッドから直接コンポーネントのマークアップを返すことができます:

    /**
* Get the view / contents that represent the component.
*/
public function render(): string
{
return <<<'blade'
<div class="alert alert-danger">
{{ $slot }}
</div>
blade;
}

インラインビューコンポーネントの生成

インラインビューをレンダリングするコンポーネントを作成するには、make:component コマンドを実行する際に inline オプションを使用できます:

php artisan make:component Alert --inline

ダイナミックコンポーネント

時には、コンポーネントをレンダリングする必要があるが、実行時までどのコンポーネントをレンダリングするかわからない場合があります。このような状況では、Laravel の組み込み dynamic-component コンポーネントを使用して、実行時の値や変数に基づいてコンポーネントをレンダリングすることができます:

// $componentName = "secondary-button";

<x-dynamic-component :component="$componentName" class="mt-4" />

コンポーネントの手動登録

警告

コンポーネントを手動で登録する方法に関する以下のドキュメントは、主にビューコンポーネントを含むLaravelパッケージを作成している方に適用されます。パッケージを作成していない場合は、このコンポーネントのドキュメントの一部は関連性がないかもしれません。

アプリケーション用のコンポーネントを作成する際、コンポーネントはapp/View/Componentsディレクトリとresources/views/componentsディレクトリ内で自動的に検出されます。

ただし、Bladeコンポーネントを利用するパッケージを構築したり、非標準のディレクトリにコンポーネントを配置したりする場合は、コンポーネントクラスとそのHTMLタグのエイリアスを手動で登録する必要があります。これにより、Laravelがコンポーネントを見つける場所を知ることができます。通常は、パッケージのサービスプロバイダのbootメソッドでコンポーネントを登録することが推奨されます:

    use Illuminate\Support\Facades\Blade;
use VendorPackage\View\Components\AlertComponent;

/**
* Bootstrap your package's services.
*/
public function boot(): void
{
Blade::component('package-alert', AlertComponent::class);
}

コンポーネントが登録されたら、そのタグエイリアスを使用してレンダリングできます:

<x-package-alert/>

パッケージコンポーネントのオートローディング

代わりに、componentNamespaceメソッドを使用して、規約に従ってコンポーネントクラスを自動的にロードすることもできます。たとえば、Nightshadeパッケージには、Package\Views\Components名前空間内に存在するCalendarColorPickerコンポーネントがあるとします:

    use Illuminate\Support\Facades\Blade;

/**
* Bootstrap your package's services.
*/
public function boot(): void
{
Blade::componentNamespace('Nightshade\\Views\\Components', 'nightshade');
}

これにより、package-name::構文を使用してベンダー名前空間でパッケージコンポーネントを使用できます:

<x-nightshade::calendar />
<x-nightshade::color-picker />

Bladeは、このコンポーネントにリンクされたクラスをパスカルケースで自動的に検出します。サブディレクトリも「ドット」表記を使用してサポートされています。

匿名コンポーネント

インラインコンポーネントと同様に、匿名コンポーネントは単一のファイルを介してコンポーネントを管理する仕組みを提供します。ただし、匿名コンポーネントは単一のビューファイルを使用し、関連するクラスがありません。匿名コンポーネントを定義するには、resources/views/componentsディレクトリ内にBladeテンプレートを配置するだけです。たとえば、resources/views/components/alert.blade.phpでコンポーネントを定義したとします。次のように簡単にレンダリングできます:

<x-alert/>

componentsディレクトリの中にコンポーネントがさらに深くネストされている場合は、.文字を使用して示すことができます。たとえば、コンポーネントがresources/views/components/inputs/button.blade.phpで定義されていると仮定すると、次のようにレンダリングできます:

<x-inputs.button/>

匿名インデックスコンポーネント

時々、コンポーネントが多くのBladeテンプレートで構成されている場合、指定されたコンポーネントのテンプレートを単一のディレクトリ内にグループ化したいと思うことがあります。たとえば、次のディレクトリ構造を持つ「アコーディオン」コンポーネントを想像してみてください:

/resources/views/components/accordion.blade.php
/resources/views/components/accordion/item.blade.php

このディレクトリ構造により、アコーディオンコンポーネントとそのアイテムを次のようにレンダリングできます:

<x-accordion>
<x-accordion.item>
...
</x-accordion.item>
</x-accordion>

ただし、x-accordionを介してアコーディオンコンポーネントをレンダリングするためには、「index」アコーディオンコンポーネントテンプレートを他のアコーディオン関連テンプレートと一緒にaccordionディレクトリにネストするのではなく、resources/views/componentsディレクトリに配置する必要がありました。

幸いにも、Bladeではコンポーネントのテンプレートディレクトリにindex.blade.phpファイルを配置することができます。コンポーネントにindex.blade.phpテンプレートが存在する場合、それはコンポーネントの「ルート」ノードとしてレンダリングされます。したがって、上記の例で示されているBlade構文を引き続き使用することができます。ただし、次のようにディレクトリ構造を調整します:

/resources/views/components/accordion/index.blade.php
/resources/views/components/accordion/item.blade.php

データプロパティ / 属性

匿名コンポーネントには関連するクラスがないため、コンポーネントに変数として渡すデータと、コンポーネントの属性バッグに配置する属性をどのように区別すべきか疑問に思うかもしれません。

コンポーネントのBladeテンプレートの先頭に@propsディレクティブを使用して、どの属性がデータ変数として考慮されるかを指定できます。コンポーネントの他のすべての属性は、コンポーネントの属性バッグを介して利用可能です。データ変数にデフォルト値を指定したい場合は、変数名を配列キーとして、デフォルト値を配列値として指定できます:

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

@props(['type' => 'info', 'message'])

<div {{ $attributes->merge(['class' => 'alert alert-'.$type]) }}>
{{ $message }}
</div>

与えられたコンポーネント定義を上記のようにレンダリングすることができます。

<x-alert type="error" :message="$message" class="mb-4"/>

親データへのアクセス

時には、子コンポーネント内で親コンポーネントからデータにアクセスしたい場合があります。このような場合、@awareディレクティブを使用することができます。たとえば、親 <x-menu> と子 <x-menu.item> から構成される複雑なメニューコンポーネントを構築していると想像してみてください:

<x-menu color="purple">
<x-menu.item>...</x-menu.item>
<x-menu.item>...</x-menu.item>
</x-menu>

<x-menu> コンポーネントは次のように実装されているかもしれません:

<!-- /resources/views/components/menu/index.blade.php -->

@props(['color' => 'gray'])

<ul {{ $attributes->merge(['class' => 'bg-'.$color.'-200']) }}>
{{ $slot }}
</ul>

color プロパティは親(<x-menu>)にのみ渡されたため、<x-menu.item>内では利用できません。しかし、@awareディレクティブを使用すると、<x-menu.item>内でも利用できるようになります:

<!-- /resources/views/components/menu/item.blade.php -->

@aware(['color' => 'gray'])

<li {{ $attributes->merge(['class' => 'text-'.$color.'-800']) }}>
{{ $slot }}
</li>
警告

@awareディレクティブは、HTML属性を介して明示的に親コンポーネントに渡されていない親データにアクセスすることはできません。@awareディレクティブでは、親コンポーネントに明示的に渡されていないデフォルトの @props 値にアクセスすることはできません。

匿名コンポーネントパス

以前に議論したように、匿名コンポーネントは通常、Bladeテンプレートを resources/views/components ディレクトリに配置することで定義されます。ただし、デフォルトのパスに加えて、Laravelに他の匿名コンポーネントパスを登録したい場合があります。

anonymousComponentPath メソッドは、最初の引数として匿名コンポーネントの場所への "パス"、2番目の引数としてコンポーネントを配置するオプションの "名前空間" を受け入れます。通常、このメソッドは、アプリケーションの サービスプロバイダboot メソッドから呼び出すべきです:

    /**
* Bootstrap any application services.
*/
public function boot(): void
{
Blade::anonymousComponentPath(__DIR__.'/../components');
}

上記の例のように、指定されたプレフィックスなしでコンポーネントパスが登録されると、Bladeコンポーネント内で対応するプレフィックスなしでレンダリングされることがあります。たとえば、上記で登録されたパスに panel.blade.php コンポーネントが存在する場合、次のようにレンダリングされるかもしれません:

<x-panel />

anonymousComponentPath メソッドの第二引数として "namespaces" プレフィックスを指定できます:

Blade::anonymousComponentPath(DIR.'/../components', 'dashboard');

プレフィックスが指定された場合、その "namespace" 内のコンポーネントは、コンポーネントがレンダリングされる際に、コンポーネント名にプレフィックスを付けてレンダリングすることができます:

<x-dashboard::panel />

レイアウトの構築

コンポーネントを使用したレイアウト

ほとんどの Web アプリケーションは、さまざまなページで同じ一般的なレイアウトを維持します。アプリケーション全体でレイアウト HTML をすべてのビューで繰り返さなければならないとしたら、アプリケーションのメンテナンスは非常に手間がかかります。幸いなことに、このレイアウトを単一の Blade コンポーネント として定義し、その後アプリケーション全体で使用することが便利です。

レイアウトコンポーネントの定義

例えば、"todo" リストアプリケーションを構築しているとします。次のような layout コンポーネントを定義するかもしれません:

<!-- resources/views/components/layout.blade.php -->

<html>
<head>
<title>{{ $title ?? 'Todo Manager' }}</title>
</head>
<body>
<h1>Todos</h1>
<hr/>
{{ $slot }}
</body>
</html>

レイアウトコンポーネントの適用

layout コンポーネントが定義されたら、そのコンポーネントを利用する Blade ビューを作成できます。この例では、タスクリストを表示するシンプルなビューを定義します:

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

<x-layout>
@foreach ($tasks as $task)
{{ $task }}
@endforeach
</x-layout>

コンポーネントに挿入されるコンテンツは、layout コンポーネント内のデフォルトの $slot 変数に供給されます。おそらく気づいたかもしれませんが、layout$title スロットも尊重します。提供された場合はカスタムタイトルを表示し、それ以外の場合はデフォルトのタイトルが表示されます。コンポーネントのドキュメント で説明されている標準のスロット構文を使用して、タスクリストビューからカスタムタイトルを挿入できます:

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

<x-layout>
<x-slot:title>
Custom Title
</x-slot>

@foreach ($tasks as $task)
{{ $task }}
@endforeach
</x-layout>

レイアウトとタスクリストビューを定義したので、ルートから task ビューを返すだけです:

    use App\Models\Task;

Route::get('/tasks', function () {
return view('tasks', ['tasks' => Task::all()]);
});

テンプレート継承を使用したレイアウト

レイアウトの定義

レイアウトは "テンプレート継承" を使用して作成することもできます。これは、コンポーネント の導入前にアプリケーションを構築する主要な方法でした。

まずは、簡単な例を見てみましょう。まず、ページレイアウトを調べてみましょう。ほとんどのWebアプリケーションは、さまざまなページで同じ一般的なレイアウトを維持しているため、このレイアウトを単一のBladeビューとして定義するのが便利です:

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

このファイルには典型的なHTMLマークアップが含まれていることがわかります。ただし、@section および @yield ディレクティブに注意してください。@section ディレクティブは、その名前が示すようにコンテンツのセクションを定義し、@yield ディレクティブは指定されたセクションの内容を表示するために使用されます。

アプリケーションのレイアウトを定義したので、このレイアウトを継承する子ページを定義しましょう。

レイアウトの拡張

子ビューを定義する際には、@extends Bladeディレクティブを使用して、子ビューがどのレイアウトを "継承" するかを指定します。Bladeレイアウトを拡張するビューは、@section ディレクティブを使用してレイアウトのセクションにコンテンツを挿入することができます。前述の例で見たように、これらのセクションの内容は @yield を使用してレイアウトに表示されます:

<!-- resources/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

この例では、sidebar セクションは、コンテンツを上書きするのではなく追加するために @@parent ディレクティブを使用しています。@@parent ディレクティブは、ビューがレンダリングされるときにレイアウトのコンテンツに置き換えられます。

注記

前の例とは対照的に、この sidebar セクションは @show ではなく @endsection で終わっています。@endsection ディレクティブはセクションを定義するだけで、@show はセクションを定義して すぐに表示 します。

@yield ディレクティブは、第二引数としてデフォルト値を受け入れることもできます。この値は、yieldされるセクションが未定義の場合にレンダリングされます:

@yield('content', 'Default content')

フォーム

CSRF フィールド

アプリケーション内で HTML フォームを定義する際は、CSRF 保護ミドルウェアがリクエストを検証できるように、フォームに隠し CSRF トークンフィールドを含める必要があります。@csrf Blade ディレクティブを使用してトークンフィールドを生成できます:

<form method="POST" action="/profile">
@csrf

...
</form>

メソッドフィールド

HTML フォームでは PUTPATCH、または DELETE リクエストを行うことができないため、これらの HTTP メソッドをスプーフィングするために、隠し _method フィールドを追加する必要があります。@method Blade ディレクティブを使用してこのフィールドを作成できます:

<form action="/foo/bar" method="POST">
@method('PUT')

...
</form>

入力エラー

@error ディレクティブを使用すると、特定の属性に対する入力エラーメッセージが存在するかどうかを素早くチェックできます。@error ディレクティブ内では、$message 変数をエコーしてエラーメッセージを表示できます:

<!-- /resources/views/post/create.blade.php -->

<label for="title">Post Title</label>

<input id="title"
type="text"
class="@error('title') is-invalid @enderror">

@error('title')
<div class="alert alert-danger">{{ $message }}</div>
@enderror

@error ディレクティブは "if" ステートメントにコンパイルされるため、属性にエラーがない場合にコンテンツをレンダリングするには、@else ディレクティブを使用できます:

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

<label for="email">Email address</label>

<input id="email"
type="email"
class="@error('email') is-invalid @else is-valid @enderror">

複数のフォームを含むページでバリデーションエラーメッセージを取得するには、@error ディレクティブの第二パラメータとして特定のエラーバッグの名前を渡すことができます:

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

<label for="email">Email address</label>

<input id="email"
type="email"
class="@error('email', 'login') is-invalid @enderror">

@error('email', 'login')
<div class="alert alert-danger">{{ $message }}</div>
@enderror

スタック

Blade では、名前付きスタックにプッシュすることができ、これらは別のビューまたはレイアウトの別の場所でレンダリングできます。これは、子ビューで必要な JavaScript ライブラリを指定する際に特に便利です:

@push('scripts')
<script src="/example.js"></script>
@endpush

特定のブール式が true に評価される場合にコンテンツを @push したい場合は、@pushIf ディレクティブを使用できます:

@pushIf($shouldPush, 'scripts')
<script src="/example.js"></script>
@endPushIf

必要な回数だけスタックにプッシュすることができます。完全なスタック内容をレンダリングするには、@stack ディレクティブにスタックの名前を渡します:

<head>
<!-- Head Contents -->

@stack('scripts')
</head>

スタックの先頭にコンテンツを追加したい場合は、@prepend ディレクティブを使用する必要があります:

@push('scripts')
This will be second...
@endpush

// Later...

@prepend('scripts')
This will be first...
@endprepend

サービスの注入

@inject ディレクティブを使用して、Laravel の サービスコンテナ からサービスを取得することができます。@inject に渡される最初の引数は、サービスが配置される変数の名前であり、2 番目の引数は解決したいサービスのクラスまたはインターフェース名です:

@inject('metrics', 'App\Services\MetricsService')

<div>
Monthly Revenue: {{ $metrics->monthlyRevenue() }}.
</div>

インライン Blade テンプレートのレンダリング

時々、生の Blade テンプレート文字列を有効な HTML に変換する必要があるかもしれません。Blade ファサードが提供する render メソッドを使用してこれを実行できます。render メソッドは、Blade テンプレート文字列とテンプレートに提供するオプションのデータ配列を受け入れます:

use Illuminate\Support\Facades\Blade;

return Blade::render('Hello, {{ $name }}', ['name' => 'Julian Bashir']);

Laravel は、インライン Blade テンプレートを storage/framework/views ディレクトリに書き込んでレンダリングします。Blade テンプレートのレンダリング後にこれらの一時ファイルを削除して欲しい場合は、メソッドに deleteCachedView 引数を指定できます:

return Blade::render(
'Hello, {{ $name }}',
['name' => 'Julian Bashir'],
deleteCachedView: true
);

Blade フラグメントのレンダリング

Turbohtmx などのフロントエンドフレームワークを使用する場合、HTTP レスポンス内で Blade テンプレートの一部のみを返す必要があることがあります。Blade "フラグメント" を使用すると、それが可能です。始めるには、Blade テンプレートの一部を @fragment@endfragment ディレクティブ内に配置します:

@fragment('user-list')
<ul>
@foreach ($users as $user)
<li>{{ $user->name }}</li>
@endforeach
</ul>
@endfragment

次に、このテンプレートを使用するビューをレンダリングする際に、fragment メソッドを呼び出して、指定されたフラグメントのみが送信されるように指定できます:

return view('dashboard', ['users' => $users])->fragment('user-list');

fragmentIf メソッドを使用すると、指定された条件に基づいてビューのフラグメントを条件付きで返すことができます。それ以外の場合は、ビュー全体が返されます:```

return view('dashboard', ['users' => $users])
->fragmentIf($request->hasHeader('HX-Request'), 'user-list');

fragments メソッドと fragmentsIf メソッドを使用すると、複数のビューフラグメントをレスポンスで連結して返すことができます。

view('dashboard', ['users' => $users])
->fragments(['user-list', 'comment-list']);

view('dashboard', ['users' => $users])
->fragmentsIf(
$request->hasHeader('HX-Request'),
['user-list', 'comment-list']
);

Blade の拡張

Blade では、directive メソッドを使用して独自のカスタムディレクティブを定義することができます。Blade コンパイラがカスタムディレクティブに遭遇すると、そのディレクティブが含む式を使用して提供されたコールバックを呼び出します。

次の例では、@datetime($var) ディレクティブを作成し、与えられた $varDateTime のインスタンスである必要があります)をフォーマットします。

    <?php

namespace App\Providers;

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

class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
// ...
}

/**
* Bootstrap any application services.
*/
public function boot(): void
{
Blade::directive('datetime', function (string $expression) {
return "<?php echo ($expression)->format('m/d/Y H:i'); ?>";
});
}
}

この例では、ディレクティブに渡された式に format メソッドを連結します。したがって、この例では、このディレクティブによって生成される最終的な PHP は次のようになります。

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

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

カスタムエコーハンドラ

Blade を使用してオブジェクトを "echo" しようとすると、オブジェクトの __toString メソッドが呼び出されます。__toString メソッドは PHP の組み込みの "マジックメソッド" の1つです。ただし、サードパーティのライブラリに属するクラスとやり取りしている場合など、特定のクラスの __toString メソッドを制御できない場合があります。

このような場合、Blade ではその特定のタイプのオブジェクトに対してカスタムエコーハンドラを登録することができます。これを実現するために、Blade の stringable メソッドを呼び出す必要があります。stringable メソッドはクロージャを受け入れます。このクロージャは、レンダリングを担当するオブジェクトのタイプを型ヒントする必要があります。通常、stringable メソッドは、アプリケーションの AppServiceProvider クラスの boot メソッド内で呼び出すべきです。

    use Illuminate\Support\Facades\Blade;
use Money\Money;

/**
* Bootstrap any application services.
*/
public function boot(): void
{
Blade::stringable(function (Money $money) {
return $money->formatTo('en_GB');
});
}

カスタムエコーハンドラを定義したら、Blade テンプレートで単純にオブジェクトをエコーすることができます。

Cost: {{ $money }}

カスタムIf文

簡単なカスタム条件文を定義する際に、カスタムディレクティブをプログラミングすることは時には不要に複雑になることがあります。そのため、Bladeはクロージャを使用して簡単にカスタム条件ディレクティブを定義できるBlade::ifメソッドを提供しています。例えば、アプリケーションの設定されたデフォルトの「disk」をチェックするカスタム条件を定義しましょう。これは、AppServiceProviderbootメソッドで行うことができます:

    use Illuminate\Support\Facades\Blade;

/**
* Bootstrap any application services.
*/
public function boot(): void
{
Blade::if('disk', function (string $value) {
return config('filesystems.default') === $value;
});
}

カスタム条件が定義されたら、テンプレート内で使用することができます:

@disk('local')
<!-- The application is using the local disk... -->
@elsedisk('s3')
<!-- The application is using the s3 disk... -->
@else
<!-- The application is using some other disk... -->
@enddisk

@unlessdisk('local')
<!-- The application is not using the local disk... -->
@enddisk