【Laravel】 コンポーネントのクラスを活用しよう

php artisan make:component Alertのようにしてコンポーネントを作成すると、resourcesだけでなくapp/View/Componentにもファイルが作成されます。ここに作成されるコンポーネントを使用してみましょう。

Componentクラスの基本

Componentを作る

php artisan make:component Alertのようにartisanを使用してコンポーネントを作成すると、ビューにコンポーネントが作成されると同時に、app/View/Componentsにクラスが作成されます。

namespace App\View\Components;

use Illuminate\View\Component;

class Alert 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|\Closure|string
     */
    public function render()
    {
        return view('components.alert');
    }
}
<div>
    <!-- Life is available only in the present moment. - Thich Nhat Hanh -->
</div>

renderを見ると、view関数でコンポーネントを返しています。そのため、コントローラからview関数を使用する時と同じ感覚で使えるということになります。

サブディレクトリに作成したい場合、php artisan make:component Hoge/Fugaのようにします。

Componentを呼び出す

作ったコンポーネントは、bladeだけのコンポーネントと同じようにビューから呼び出すことができますが、x-クラス名のように、クラス名をケバブケースにしたものを用います。

class Alert extends Component
{
    // ...
}
<x-alert>
    <!-- ... -->
</x-alert>

タグに指定する名前は、app/View/Componentsresources/views/componentsから対応するものが検索されます。そのため、クラスがなくても (bladeだけでも) 使用できます。クラスがある場合はクラスのほうが使用されます。

また、コンポーネントのインスタンスは、表示するコンポーネントごとに独立しています。

コンポーネントのクラスからViewに値を渡す

作成されたコンポーネントのクラスに軽く実装して、Viewのコンポーネントに値を渡してみましょう。

ビューのコンポーネント
<div>
    {{ $hoge }}

    {{ $slot }}
</div>
コンポーネント
class Alert extends Component
{
    // ...

    public function render()
    {
        $hoge = 'abcde';
        
        return view('components.alert', compact(
            'hoge',
        ));
    }
}
ビュー
<x-alert>slotの中身</x-alert>

そうすると、{{ $hoge }}にはabcdeが、{{ $slot }}にはビューで渡したDOMが表示されることが分かります。

また、クラスのコンポーネントから渡した変数名と、ビューからnameを指定した名前が被った場合 (つまり、2箇所で{{ $hoge }}を指定したなど) 、ビューで指定したほうが優先されます。

ビューのコンポーネント
<div>
    {{ $hoge }}

    {{ $slot }}
</div>
コンポーネント
class Alert extends Component
{
    // ...

    public function render()
    {
        $hoge = 'abcde';
        
        return view('components.alert', compact(
            'hoge',
        ));
    }
}
ビュー
<x-alert>
    <!-- こっちの値が優先される -->
    <x-slot name="hoge">hogehoge</x-slot>
    slotの中身
</x-alert>
result
<div>
    hogehoge

    slotの中身
</div>

コンポーネントに値を渡す

今までは属性に値を入れたり、slotに値を入れ、コンポーネントでは{{ $hoge }}のようにしてそれを表示するだけでした。クラスを使用することで、その値をコンポーネントのクラスに送ることができます。

送られた値は、コンストラクタで属性名と同じ名前の変数で取り出すことができます。ルートパラメータと違い、順番ではありません。

<x-alert hoge="aaaaa" fuga="bbbbb">
    slotの中身
</x-alert>
class Alert extends Component
{
    private $hoge;
    private $fuga;

    // ビューで属性に入れたものが入ってくる
    // 順番ではなく、属性名と対応する名前に入ってくる
    public function __construct($fuga, $hoge)
    {
        $this->fuga = $fuga;
        $this->hoge = $hoge;
    }

    public function render()
    {        
        return view('components.alert', [
            'hoge' => $this->hoge,
            'fuga' => $this->fuga,
        ]);
    }
}

属性名がケバブケースの場合、変数名はキャメルケースになります。

<x-alert abc-foo="hoge">...</x-alert>なら、__construct($abcFoo)のようにします。

もちろん、コントローラの時と同様にモデルを取得したりといったことも可能です。

@for ($i = 1; $i <= 3; $i++)
    <x-alert :note-id="$i" />
@endfor
use App\Models\Note;

class Alert extends Component
{
    private $note;

    public function __construct($noteId)
    {
        // モデルを取得
        $this->note = Note::find($noteId);
    }

    public function render()
    {
        return view('components.alert', [
            'content' => $this->note->content,
        ]);
    }
}

まとめ

クラスのコンポーネントは、渡された値を様々な形で活用することで力を発揮します。例えばデータベースからデータを取得する、データを整形するなど、様々な活用方法があります。

様々な処理をコントローラではなく、コンポーネントに書いたほうが綺麗にならないか試してみましょう。

laravel component thumb

役に立ったらシェアしよう!