コンポーネントクラスの使い所

2021-03-17
3 min read

前回、トップページにキャンペーン応募を促すメッセージを表示するというケースでDIの説明をしました。

今回、編集画面などすべてのページに前回のメッセージを表示するケースを想定してみました。
すべてのページにメッセージを表示するには、コントローラクラスの index メソッドに記述したコードをほかのメソッドにも記述することで実現できます。 しかし、それはあまりにも冗長です。

こういうときの解決方法として使えるのが、コンポーネントクラスです。

環境

今回の開発環境は以下の通りです。

  • Laravel 8
  • PHP 8

実装

artisanコマンドにてコンポーネントクラスを生成

コンポーネントクラスをコマンドで作成します。

$ php artisan make:component Campaign
Component created successfully.

下記の2つが作成されます。

  • app/View/Components/Campaign.php
  • resources/views/components/campaign.blade.php

make:componentコマンドは、コンポーネントクラスに加えて、コンポーネントのビューテンプレートも作成してくれるので便利です。

それぞれの生成後の中身をみていきます。

Campaign.php の方は、render()に view が指定されています。 このrender()が呼ばれて描画されることになります。

<?php

namespace App\View\Components;

use Illuminate\View\Component;

class Campaign extends Component
{
    /**
     * Create a new component instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Get the view / contents that represent the component.
     *
     * @return \Illuminate\Contracts\View\View|string
     */
    public function render()
    {
        return view('components.campaign');
    }
}

blade ファイルの方は、下記になります。

<div>
    <!-- Simplicity is the ultimate sophistication. - Leonardo da Vinci -->
</div>

これらは、app/View/Componentsディレクトリとresources/views/componentsディレクトリに配置されます。 これらのディレクトリのものは、Laravel が自動的に検知するためコンポーネント登録が必要ありません。

Componentクラスの実装

app/View/Components/Campaign.phpの実装をします。

<?php

namespace App\View\Components;

use Illuminate\View\Component;
use App\Models\User;
use App\Services\CampaignService;
use Illuminate\Support\Facades\Auth;

class Campaign extends Component
{

    public $massages;

    /**
     * Create a new component instance.
     *
     * @return void
     */
    public function __construct(CampaignService $camp)
    {
        $this->massages = $camp->getCampaignMassage(Auth::user());
    }

    /**
     * Get the view / contents that represent the component.
     *
     * @return \Illuminate\Contracts\View\View|string
     */
    public function render()
    {
        return view('components.campaign');
    }
}

コントローラクラスの index メソッドに実装したものをコンストラクタに移動しただけです。 移動したコントローラクラスの index メソッドは下記になります。

    public function index()
    {
        return view('welcome');
    }

すごくスッキリしました。

Viewの実装

resources/views/components/campaign.blade.phpを実装します。

<div>
    @foreach ($massages as $msg)
                @auth 
                    <a href="{{ route($msg[Camp::MSG_LINK]) }}" >{{$msg[Camp::MSG_BODY]}}</a>
                @endauth    
    @endforeach
</div>

resources/views/welcome.blade.phpに記載したものを移動します。

$massages ですが、前回は index メソッドにview('welcome', compact('massages'));と VIEW ヘルパーの第 2 引数に指定していました。 コンポーネントクラスの場合はその必要がなく、コンポーネントクラスのプロパティが呼ばれることになります。

コンポーネントクラスの呼び出し

resources/views/welcome.blade.phpからコンポーネントクラスを呼ぶことになります。

前回、実装した下記の部分をコンポーネントクラスを表すタグ<x-campaign /> にします。

    @foreach ($massages as $msg)
                @auth 
                    <a href="{{ route($msg[Camp::MSG_LINK]) }}" >{{$msg[Camp::MSG_BODY]}}</a>
                @endauth    
    @endforeach

タグは、<x-{クラス名} />になります。クラス名は、アッパーキャメルケース(パスカルケース)ですが、ここでは単語の間をハイフンでつなぐケバブケースになります。

テスト

前回作成した機能テストを再実行します。

php artisan test tests/Feature/CampaignServiceTest.php

エラーがなければ合格です。ただし、かなり簡単なテストですので実際はテストケースを増やします。

まとめ

あとは、土台となるlayout.blade.php<x-campaign /> タグを記述することで、全画面にキャンペーンメッセージが表示されます。 さらに詳細な使い方は下記のコンポーネントのセクションをみてください。

https://readouble.com/laravel/8.x/ja/blade.html