35
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Laravel / Blade】Bladeでの処理はこれで完璧!

Last updated at Posted at 2023-09-07

はじめに

こんにちは、エンジニア2年目の嶋田です。
まずは、この記事を開いていただきありがとうございます!

今回は、LaravelのBladeディレクティブについて解説したいと思います。
最後までお付き合いください!

目次

Bladeとは

Laravelのview作成にはHTMLではなくBladeが使用されます。
ベースとなる書き方はHTMLですが、加えてBlade固有の色々な機能を使用することができます。
Bladeを使うと、テンプレートを継承したり、レイアウトの一部をセクションの一部としてはめ込むことができます。
効率的にレイアウトを作成したいならBladeを使うといいと思います!

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

上記、公式より引用

ディレクティブについて

構文のような役割を果たすものでテンプレートに簡単に組み込むことができます。
@から始まる範囲内で特定の処理を実行することができる記述方法です。

 
@include('layouts.footer') 
 
@include('layouts.header', ["banana" => 'yellow'])

ディレクティブの利点は動的な部分のコードを比較的少ないコードで記述が可能となることです。

分岐

分岐のディレクトリは以下のようにまとめられます。

ディレクティブ 役割
@if(条件) 条件分岐
@unless(変数) 条件非成立の時表示
@empty(変数) 変数が空の場合表示
@isset(変数) 変数が定義済みの場合表示
@switch 複数の条件に基づいた分岐処理を実行

if

@if@elseif@else@endifディレクティブを使用してif文を作成できます。
これらのディレクティブは、対応するPHPの構文と同じように機能します。
使用例は以下の通りです。

@if (count($records) === 1)
    レコードあります
@elseif (count($records) > 1)
    複数レコードあります
@else
    レコードがありません
@endif

unless

unlessはifと逆の動きをします。
要は判定がfalseの場合に生じる処理が実行されるということです。

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

empty

emptyは変数内が空の時に実行されるという書き方です。
空文字列, null, 0などの時にtrueとなります。

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

isset

issetはその変数が定義済みでnullではない時に実行されるという書き方です。
定義されていた場合にtrueとなります。

@isset($records)
    // $recordsが定義済みで、NULLではない…
@endisset

上記、empty,issetに関しては判定が複雑なので私はこちらの早見表をよくみていました。

switch

switch文は、@switch@case@break@default@endswitchディレクティブを使用して作成できます。
これらのディレクティブは、対応するPHPの構文と同じように機能します。
使用例は以下の通りです。

@switch($i)
    @case(1)
        最初のケース
        @break

    @case(2)
        番めのケース
        @break

    @default
        デフォルトのケース
@endswitch

認証ディレクティブ

こちらは非常に便利です。
@authおよび@guestディレクティブを使用すると、現在のユーザーが認証済みであるか、ゲストであるかを簡潔に判断できます。使用例は以下の通りです。

@auth
    // ユーザーは認証済み…
@endauth
@guest
    // ユーザーは認証されていない…
@endguest

環境ディレクティブ

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

@production
    // Production限定コンテンツ…
@endproduction

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

@env('staging')
    // アプリケーションは"staging"で動作している…
@endenv

@env(['staging', 'production'])
    // アプリケーションは"staging"か"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

繰り返し

条件文に加えて、BladeはPHPのループ構造を操作するための簡単なディレクティブを提供します。繰り返しますが、これらの各ディレクティブは、対応するPHPと同じように機能します。

今回は記載していませんが、@continueおよび@breakディレクティブを使用して、反復をスキップするか、ループを終了することもできます。

繰り返しのディレクトリは以下のようにまとめられます。

ディレクティブ 役割
@for(初期化 ; 条件; 後処理;) PHPのfor構文に相当するもの
@foreach(配列, 変数) PHPのforeach構文に相当するもの
@while(条件) PHPのwhile構文に相当するもの

for

for文として使用できます。指定の回数処理を繰り返す場合に有効です。

@for ($i = 0; $i < 10; $i++)
    現在の値は{{ $i }}
@endfor

while

while文として使用できます。
指定した条件がtrueの間はループし続けます。

@php 
    $counter = 0;
@endphp
@while ($counter < 10)
    <p>現在の値は {{ $counter }}</p>

    @php
        $counter++;
    @endphp
@endwhile

foreach

foreach文として使用できます。
配列やコレクションの要素分ループします。ループ処理のなかでは最もよく使うと思います。

@foreach ($users as $user)
    <p>このユーザーは{{ $user->id }}</p>
@endforeach

forelse

foreachと同じく配列やコレクションの要素をループします。
foreachに加え、配列やコレクションに要素が存在しない場合の処理を@emptyディレクティブに記述することができます。

@forelse ($users as $user)
    <li>{{ $user->name }}</li>
@empty
    <p>ユーザーはいません</p>
@endforelse

ループ変数

Bladeでは、$loopという繰り返し処理で使用できる特殊な変数が存在します。
「$loop->取り出したい値」とアクセスすることで、様々なプロパティにアクセスすることが可能となります。
繰り返しのディレクティブに用意されている変数 $loopの使い方は以下の通りです。

ループ変数 役割
$loop->index 現在のインデックス(0~)
$loop->iteration 現在の繰り返し数(1~)
$loop->remaining 後何回繰り返すのか
$loop->count 繰り返しで使っている配列の要素数
$loop->first 最初の繰り返しかどうか
$loop->last 最後の繰り返しかどうか
$loop->depth 繰り返しのネスト数
$loop->parent ネストしている場合、親の繰り返しループ変数を示す

foreachループの反復処理中、ループの内部では$loop変数を利用できます。
この変数により、現在のループのインデックスや、ループの最初の反復なのか最後の反復なのか、といった便利な情報にアクセスすることができます。

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

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

    <p>このユーザーは{{ $user->id }}</p>
@endforeach

ネストしたループ内にいる場合は、parentプロパティを介して親ループの$loop変数にアクセスできます。

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

ちなみに、ネストとは、あるものの中に、それと同じ形や種類の(一回り小さい)ものが入っている状態や構造のことです!

レイアウト作成用

レイアウト作成時に必要なディレクティブは以下のようにまとめられます。

ディレクティブ 役割
@section(名前) 指定した名前でセクションが用意される
@yield(名前) 配置場所を示すもの
@extends(Bladeのファイル名) レイアウトの継承設定
@parent 親レイアウトのセクションを示す
@component(名前) コンポーネントの組み込み
@slot(名前) コンポーネントに動的なコンテンツを挿入する
@include(読み込むテンプレート名, [値の指定]) サブビューの読み込み
@each(テンプレート名, 配列, 配列から取り出したデータを入れる変数名) 配列などから値を取り出し指定のテンプレートにはめ込んで出力する

section

@sectionディレクティブは、テンプレート内でセクションを定義するために使います。
セクションは、後で他のテンプレートで展開するために内容を保持するものです。
例えば、ウェブページのタイトルやコンテンツ部分を定義するのに役立ちます。

セクションを定義するには、@sectionディレクティブにセクション名を第一引数に指定し、その中にHTMLやテキストを記述します。使用例は以下の通りです。

@section('title', 'laratimes')

@section('content')
    <div>
        {{ $hoge }}
    </div>
@endsection

titlecontentという2つのセクションを定義しています。これらのセクションは、後で@yieldディレクティブを使用して展開することができます。

yield

@yieldディレクティブは、@sectionディレクティブで定義されたセクションを展開します。
指定したセクション名を引数として渡すことで、そのセクションの内容を表示できます。

@yield('content')

このコードは、contentセクションの内容を表示します。
また、第二引数を指定することで、セクションが未定義の場合に代替コンテンツを表示することもできます。

@yield('content', View::make('view.id'))

上記の例では、contentセクションが未定義の場合にview.idテンプレートを表示します。

extend

@extendsディレクティブは、親レイアウトを子ビューに継承させるために使います。
親レイアウト内で@yieldディレクティブで定義したセクションを、子ビュー内で具体的なコンテンツで埋めることができます。

@extends('layouts.app')

この例では、layouts.appテンプレートを親レイアウトとして継承しています。

parent

@parent ディレクティブは、親レイアウトからセクションの内容を引き継ぐために使用されます。通常、親レイアウトで定義されたセクションを子ビューで上書きすることができますが、一部の場合にはセクションの内容を拡張したり、追加したりしたい場合があります。その際に @parent ディレクティブが役立ちます。

例えば、親レイアウトで以下のようにセクションが定義されているとします。

@section('content')
    <div>
        親レイアウトのコンテンツ
    </div>
@endsection

子ビューで同じセクションを上書きしつつ、親レイアウトの内容も表示したい場合、@parentディレクティブを使用します。

@extends('layouts.app')

@section('content')
    @parent
    <div>
        子ビューの追加コンテンツ
    </div>
@endsection

この例では、@parentディレクティブを使用して親レイアウトのコンテンツを引き継ぎつつ、子ビュー独自のコンテンツを追加しています。最終的に、親レイアウトのコンテンツと子ビューの追加コンテンツが合わさって表示されます。

include

each

componentとslot

@componentディレクティブを使用すると、コンポーネントをビューに組み込むことができます。
コンポーネントは再利用可能な部品で、ビュー内で何度も使うことができます。

@component('components.header')
    @slot('header_title')
        ページタイトル
    @endslot

    @slot('header_content')
        <li>項目1</li>
        <li>項目2</li>
    @endslot
@endcomponent

上記の例では、components.headerコンポーネントをビューに組み込んでいます。
@slotディレクティブを使用して、コンポーネント内のスロットに値を設定しています。

細かい解説はこちらをご覧ください…

include

この記事の冒頭ディレクティブの書き方の際にも出てきた@includeです。
@includeディレクティブを使用すると、他のテンプレートを読み込むことができます。
第一引数に読み込みたいテンプレートの名前を指定し、必要に応じて第二引数にテンプレートに渡す値を配列で指定できます。

@include('layouts.footer')

@include('layouts.header', ["banana" => 'yellow'])

上記の例では、layouts.footerlayouts.headerテンプレートを読み込んでいます。
["banana" => 'yellow']のように第二引数に値を渡すことができます。

each

@eachディレクティブを使用すると、配列やコレクションから値を取り出し、指定のテンプレートに組み込んで出力することができます。これを使って、繰り返し表示する要素を簡単に生成できます。

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

上記の例では、view.nameテンプレートを$jobs配列から取り出した値を使って繰り返し表示しています。
また、jobという変数名を指定しています。

HTML要素に追加

HTML要素に追加するディレクティブは以下のようにまとめられます。

ディレクティブ 役割
@class 指定したクラス名を条件に基づいて追加する
@style 指定したスタイルを条件に基づいて追加する
@checked チェックボックスのchecked属性を条件に基づいて追加する
@selected セレクトボックスのオプションにselected属性を条件に基づいて追加する
@disabled HTML要素にdisabled属性を条件に基づいて追加する。
@readonly HTML要素にreadonly属性を条件に基づいて追加する
@required HTML要素にrequired属性を条件に基づいて追加する

class

@classを使って、条件に応じてクラスを追加できます。
条件付きクラスは、HTML要素にクラス(スタイルやデザインを適用するための指示)を追加する方法です。

たとえば、ウェブページで「ログインしているかどうか」や「エラーが発生しているかどうか」によって、要素のスタイルを変えたい場合があります。以下はその例です。

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

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

このコードでは、$isLoggedIntrueの場合はfont-boldクラスを追加し、$isLoggedInfalseの場合はtext-gray-500クラスを追加します。また、$hasErrortrueの場合はbg-redクラスを追加します。
これにより、条件に応じて要素のスタイルを変更できます。

style

@styleを使って、条件に応じてスタイルを適用できます。
条件付きスタイルは、HTML要素にインラインのCSSスタイルを追加する方法です。

たとえば、特定の状況で背景色やフォントの太さを変えたい場合があります。以下はその例です。

@php
    $isActive = true;
@endphp

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

このコードでは、$isActivetrueの場合は背景色を赤にし、$isActivefalseの場合は太字のフォントを適用します。
これにより、条件に応じて要素のスタイルをカスタマイズできます。

checked

@checkedディレクティブを使用すると、指定したHTMLのチェックボックス入力がcheckedであることを条件に基づいて設定できます。

たとえば、フォームでユーザーが事前にチェックしたい場合、次のように使えます。

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

このコードでは、old関数とユーザーモデルから取得した値に基づいて、チェックボックスが事前にチェックされるかどうかを制御します。

selected

@selectedディレクティブは、セレクトボックスのオプションにselected属性を条件に基づいて追加します。
たとえば、特定のバリューが選択済みであるかどうかを制御したい場合、次のように使用します。

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

このコードでは、old関数を使用してフォームの以前のバリューを取得し、選択したバリューと一致するオプションにselected属性を追加します。

disabled

@disabledディレクティブは、指定したHTML要素にdisabled属性を条件に基づいて追加します。
たとえば、エラーが発生した場合に送信ボタンを無効にする場合、次のように使えます。

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

このコードでは、$errors->isNotEmpty()の条件に基づいて送信ボタンが無効になります。

readonly

@readonlyディレクティブを使用すると、指定したHTML要素にreadonly属性を条件に基づいて追加します。
たとえば、特定のユーザーが編集できないようにする場合、次のように使えます。

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

このコードでは、$user->isNotAdmin()の条件に基づいて、メール入力フィールドが読み取り専用になります。

required

@requiredディレクティブは、指定したHTML要素にrequired属性を条件に基づいて追加します。
たとえば、特定の条件下でフォームフィールドを必須にする場合、次のように使えます。

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

このコードでは、$user->isAdmin()の条件に基づいて、タイトル入力フィールドが必須になります。

onceディレクティブ

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

@once
    @push('scripts')
        <script>
            // カスタムJavaScript…
        </script>
    @endpush
@endonce

このコードでは、@onceディレクティブ内のコードブロックは1回だけ評価され、その後のレンダリングサイクルでは無視されます。これにより、不要な重複を避けてカスタムJavaScriptを追加できます。

@onceディレクティブは、通常、@push@prependディレクティブと組み合わせて使用されます。
便利な@pushOnce@prependOnceディレクティブも用意されており、使用例は以下の通りです。

@pushOnce('scripts')
    <script>
        // カスタムJavaScript…
    </script>
@endPushOnce

これで、同じJavaScriptコードが重複して追加されるのを防ぎながら、必要な部分にJavaScriptを追加できます。

生PHP

状況によっては、PHPコードをビューに埋め込めると便利ですよね。
@phpディレクティブを使用して、テンプレート内でプレーンPHPのブロックを定義し、実行することが可能です。

@php
    $counter = 1;
@endphp

また、PHP文を1つ書くだけなら、@phpディレクティブ内に含められます。

@php($counter = 1)

最後に

記事を読んでくださり、ありがとうございます!
長くなってしまいましたが、少しでもお役に立てたら嬉しいです。
Bladeディレクティブは、便利でコードの簡略化につながるところが魅力ですよね。
私自身もまだまだ学びの途中なので、もし何か誤った情報がありましたら、コメントでご指摘いただければ幸いです!

35
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
35
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?