コンテンツへスキップ

ブレードテンプレート

はじめに

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']);
});

LivewireによるBladeの強化

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

データの表示

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

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

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

Hello, {{ $name }}.
lightbulb

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の{{ }}文は、XSS攻撃を防ぐために、自動的にPHPのhtmlspecialchars関数を通過します。データのエスケープを望まない場合は、次の構文を使用できます。

Hello, {!! $name !!}.
exclamation

アプリケーションのユーザーから提供されたコンテンツをエコーする際は、細心の注意を払ってください。ユーザーが提供したデータを表示する際には、通常、エスケープされた二重波括弧構文を使用して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.parseJavaScript文を返します。

<script>
var app = {{ Illuminate\Support\Js::from($array) }};
</script>

最新バージョンのLaravelアプリケーションスケルトンには、Jsファサードが含まれており、Bladeテンプレート内でこの機能に簡単にアクセスできます。

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

Js::fromメソッドは、既存の変数をJSONとしてレンダリングする場合にのみ使用してください。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文

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

@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
lightbulb

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"
@readonly($user->isNotAdmin())
/>

さらに、@requiredディレクティブを使用して、特定の要素を「必須」にするかどうかを示すことができます。

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

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

lightbulb

@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'])
exclamation

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')
exclamation

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

@onceディレクティブ

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

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

@onceディレクティブは多くの場合、@pushまたは@prependディレクティブと組み合わせて使用されるため、便宜上@pushOnceおよび@prependOnceディレクティブを使用できます。

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

生のPHP

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

@php
$counter = 1;
@endphp

または、クラスのインポートにのみPHPを使用する必要がある場合は、@useディレクティブを使用できます。

@use('App\Models\Flight')

インポートされたクラスにエイリアスを付けるには、@useディレクティブに2番目の引数を指定できます。

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

コメント

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

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

コンポーネント

コンポーネントとスロットは、セクション、レイアウト、インクルードと同様の利点を提供しますが、コンポーネントとスロットのメンタルモデルの方が理解しやすいと感じる人もいます。コンポーネントの作成には、クラスベースのコンポーネントと匿名コンポーネントの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名前空間に存在するCalendarおよびColorPickerコンポーネントがある場合があります。

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テンプレートの1つにBladeコンポーネントタグを使用できます。Bladeコンポーネントタグは、文字列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;
}

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

コンポーネントがコンポーネントグループの一部である場合があり、関連するコンポーネントを単一のディレクトリ内にグループ化したい場合があります。たとえば、次のクラス構造を持つ「カード」コンポーネントを考えてみます。

App\Views\Components\Card\Card
App\Views\Components\Card\Header
App\Views\Components\Card\Body

ルートCardコンポーネントはCardディレクトリ内にネストされているため、<x-card.card>を介してコンポーネントをレンダリングする必要があると予想される場合があります。ただし、コンポーネントのファイル名がコンポーネントのディレクトリ名と一致する場合、Laravelは自動的にそのコンポーネントが「ルート」コンポーネントであると仮定し、ディレクトリ名を繰り返さずにコンポーネントをレンダリングできます。

<x-card>
<x-card.header>...</x-card.header>
<x-card.body>...</x-card.body>
</x-card>

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

HTML属性を使用して、Bladeコンポーネントにデータを渡すことができます。ハードコーディングされたプリミティブ値は、単純な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" />

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

Alpine.jsなどのJavaScriptフレームワークもコロン接頭辞の属性を使用するため、属性がPHP式ではないことをBladeに知らせるには、二重コロン(`::`)接頭辞を使用できます。例えば、以下のコンポーネントの場合

<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`メソッドからクロージャを返す必要があります。

use Closure;
 
/**
* Get the view / contents that represent the component.
*/
public function render(): Closure
{
return function () {
return '<div {{ $attributes }}>Components content</div>';
};
}

コンポーネントの`render`メソッドによって返されるクロージャは、唯一の引数として`$data`配列を受け取ることもできます。この配列には、コンポーネントに関する情報を提供するいくつかの要素が含まれます。

return function (array $data) {
// $data['componentName'];
// $data['attributes'];
// $data['slot'];
 
return '<div {{ $attributes }}>Components content</div>';
}
exclamation

`$data`配列の要素は、`render`メソッドによって返されるBlade文字列に直接埋め込まないでください。そうすると、悪意のある属性コンテンツを介してリモートコード実行を許可する可能性があります。

`componentName`は、`x-`接頭辞の後のHTMLタグで使用される名前と同じです。したがって、``の`componentName`は`alert`になります。`attributes`要素には、HTMLタグに存在するすべての属性が含まれます。`slot`要素は、コンポーネントのスロットの内容を含む`Illuminate\Support\HtmlString`インスタンスです。

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

追加の依存関係

コンポーネントがLaravelの[サービスコンテナ](/docs/11.x/container)から依存関係を必要とする場合、コンポーネントのデータ属性の前にそれらをリストアップすると、コンテナによって自動的に注入されます。

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

`@env`などのディレクティブをコンポーネントタグ内で使用することは、現時点ではサポートされていません。例えば、``はコンパイルされません。

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

属性のデフォルト値を指定したり、コンポーネントの属性の一部に追加の値をマージしたりする必要がある場合があります。これを実現するには、属性バッグの`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>
lightbulb

マージされた属性を受け取らない他のHTML要素にクラスを条件付きでコンパイルする必要がある場合は、[ `@class`ディレクティブ](#conditional-classes)を使用できます。

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

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

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

カスタム`type`でボタンコンポーネントをレンダリングするには、コンポーネントを使用するときに指定できます。 typeを指定しないと、`button` typeが使用されます。

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

コンポーネントにコンテンツを挿入することで、スロットにコンテンツを渡すことができます。

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

さらに、`hasActualContent`メソッドを使用して、スロットがHTMLコメントではない「実際の」コンテンツを含むかどうかを確認できます。

@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コンポーネントと同様に、CSSクラス名などの追加の[属性](#component-attributes)をスロットに割り当てることができます。

<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" />

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

exclamation

コンポーネントの手動登録に関する以下のドキュメントは、主にビューコンポーネントを含む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名前空間に存在するCalendarおよびColorPickerコンポーネントがある場合があります。

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テンプレートで構成されている場合、特定のコンポーネントのテンプレートを単一のディレクトリにグループ化したい場合があります。たとえば、次のディレクトリ構造を持つ「accordion」コンポーネントを考えてみましょう。

/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」アコーディオンコンポーネントテンプレートをresources/views/componentsディレクトリに配置する必要があり、他のアコーディオン関連テンプレートとネストすることができませんでした。

ありがたいことに、Bladeでは、コンポーネントのディレクトリ名と一致するファイルをコンポーネントのディレクトリ自体に配置できます。このテンプレートが存在する場合、ネストされているにもかかわらず、コンポーネントの「ルート」要素としてレンダリングできます。そのため、上記の例で示したBlade構文をそのまま使用できますが、ディレクトリ構造を次のように調整します。

/resources/views/components/accordion/accordion.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>
exclamation

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

匿名コンポーネントのパス

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

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

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

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

<x-panel />

プレフィックス「名前空間」は、anonymousComponentPathメソッドの2番目の引数として提供できます。

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

プレフィックスが提供されている場合、その「名前空間」内のコンポーネントは、コンポーネントがレンダリングされるときに、コンポーネントの名前の前に名前空間のプレフィックスを付けることでレンダリングできます。

<x-dashboard::panel />

レイアウトの構築

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

ほとんどのウェブアプリケーションは、さまざまなページで同じ一般的なレイアウトを維持しています。作成するすべてのビューでレイアウト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)
<div>{{ $task }}</div>
@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)
<div>{{ $task }}</div>
@endforeach
</x-layout>

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

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

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

レイアウトの定義

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

始めましょう。簡単な例を見てみましょう。まず、ページレイアウトを見てみましょう。ほとんどのウェブアプリケーションはさまざまなページで同じ一般的なレイアウトを維持しているため、このレイアウトを単一の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ディレクティブは、ビューがレンダリングされるときにレイアウトのコンテンツに置き換えられます。

lightbulb

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

@yieldディレクティブは、2番目のパラメータとしてデフォルト値も受け入れます。この値は、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ディレクティブの2番目のパラメータとして渡して、複数のフォームを含むページのバリデーションエラーメッセージを取得できます。

<!-- /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テンプレート文字列を有効な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
);

ブレードフラグメントのレンダリング

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

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

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

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)ディレクティブを作成します。これは、DateTimeのインスタンスである必要がある指定された$varをフォーマットします。

<?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'); ?>
exclamation

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

カスタムエコーハンドラー

Bladeを使用してオブジェクトを「出力」しようとすると、オブジェクトの__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メソッドを提供しており、これを使用してクロージャを使用してカスタム条件ディレクティブを簡単に定義できます。たとえば、アプリケーションの構成済みのデフォルト「ディスク」をチェックするカスタム条件を定義してみましょう。これは、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