Laravel 7.x のコンポーネントについて

これは、Laravel 7.15.0 の環境でのコンポーネントの利用方法についてになります。

コンポーネントの切り出し方については、これといって正解はなくて、各アプリケーションによると思うので、こういう風に作りましょうという形ではなくて、こういったパターンでも作れますよ。という形で紹介していきます。

Laravelでは、Bladeのコンポーネントと、Vueのコンポーネントが利用できるのですが、結構似たような使い方ができるので、どちらを使うか迷うかと思うので、何回かに分けてざっと機能や使い方を紹介してみます。

今回は、Bladeのコンポーネントの基本的な使い方を紹介します。

実際にここをコンポーネントかする意味はあるのかは別にして、
コンテンツ一覧ページを例にコンポーネント化していきます。

まずは、コンポーネント前の状態です。


```php:Content.php
<?php

namespace App\Http\Controllers;

class Contents extends Controller
{
  
  public function list()
  {
    $contents_list = \DB::table('contents')->paginate(10);
    
    return view('contents.list',['contents_list' => $contents_list]);
  }
}
```

```php:list.blade.php
<h1>コンテンツ一覧</h1>

{{ $contents_list->total() }}

  <div class="card">
  <table class="table">
  @foreach ($contents_list as $contents)
    <tr>
      <td><a href="/contents/info/{{ $contents->id }}">{{ $contents->title }}</a></td>
      <td>{{ $contents->create_time }}</td>
      <td><a href="/contents/remove/{{ $contents->id }}" class="btn btn-danger">削除</a></td>
    </tr>
  @endforeach
  </table>
  </div>

{{ $contents_list->links() }}

```

まずは大きめに、ページタイトルを残して一覧テーブルを丸ごとコンポーネント化してみます。

下記のコマンドでコンポーネントに必要なクラスとbladeファイルが生成されます。

```terminal
php artisan make:component ContentsList
```

下記の2ファイルが追加されたことが確認できるかと思います。
ContentListは、bladeファイルでは、contents-listとなります。

```terminal
app/View/Components/ContentsList.php
resources/views/components/contents-list.blade.php
```

この後ページに作成したコンポーネントを追加するには、下記のようにするだけです。

```php:list.blade.php
<h1>コンテンツ一覧</h1>

<x-contents-list />
```

Bladeファイル名に x- を付与したタグを挿入する形です。

まだ、コンポーネントの中身が空なので、この状態だと何も表示されないのでBladeファイルに試しに追加してみます。

```php:contents-list.php
<div>コンテンツ一覧表です</div>
```

これで、ページにコンテンツが追加されていることが確認できるかと思います。

では、実際にコンテンツの一覧表を表示します。
まずは、ContentsList.phpを編集します。

```php:ContentsList.php
<?php

namespace App\View\Components;
use Illuminate\View\Component;

class ContentsList extends Component
{
  
    public $contents_list;

    public function __construct($contents_list)
    {
        $this->contents_list = $contents_list;
    }

    public function render()
    {
        return view('components.contents-list');
    }
}
```

コンポーネントでは、クラスのパブリックプロパティがビューで利用可能になります。
また、コンポーネントへは、constructの引数を通して値を渡すことができます。
上記の例では、コンテンツ一覧のデータを、constructで受け取って、ビューで利用可能なように、
パブリックプロパティに渡しています。

次に、Bladeファイルを記述します。

```php:contents-list.php

{{ $contents_list->total() }}

  <div class="card">
  <table class="table">
  @foreach ($contents_list as $contents)
    <tr>
      <td><a href="/contents/info/{{ $contents->id }}">{{ $contents->title }}</a></td>
      <td>{{ $contents->create_time }}</td>
      <td><a href="/contents/remove/{{ $contents->id }}" class="btn btn-danger">削除</a></td>
    </tr>
  @endforeach
  </table>
  </div>

{{ $contents_list->links() }}

```

内容は、元々のソースと同じです。

これでコンポーネント側の準備が整ったので、最後にページ側からコンポーネントを呼び出す際に、コンテンツ一覧のデータの受け渡しを追加します。

```php:list.blade.php
<h1>コンテンツ一覧</h1>

<x-contents-list :contents_list="$contents_list" />
```

これで、コンポーネントを利用して、コンテンツ一覧を表示できたかと思います。

ちなみに、文字列等を渡す場合は、： なしで渡します。

```php:list.blade.php
<h1>コンテンツ一覧</h1>

<x-contents-list :contents_list="$contents_list" description="コンテンツの一覧を表示しています" />
```


次は、コンテンツ一覧全体ではなく、行をコンポーネントしてみます。
コンポーネントの作成は同様に

```terminal
$ php artisan make:component Rows
```

下記の2ファイルが生成されます。

```terminal
app/View/Components/Rows.php
resources/views/components/rows.blade.php
```

コンポーネント側を準備します。まずはViewクラス

```php:Rows.php

<?php

namespace App\View\Components;
use Illuminate\View\Component;

class Rows extends Component
{
    
    public $contents;

    public function __construct($contents)
    {
        $this->contents = $contents;
    }

    public function render()
    {
        return view('components.rows');
    }
}
```

前回と違って、今回はコンテンツ一覧全体ではなく、コンテンツ単体を受け渡しています。

次にBladeファイル側です。

```php:rows.blade.php
<tr>
  <td><a href="/contents/info/{{ $contents->id }}">{{ $contents->title }}</a></td>
  <td>{{ $contents->create_time }}</td>
  <td><a href="/contents/remove/{{ $contents->id }}" class="btn btn-danger">削除</a></td>
</tr>
```

1行分を記述しています。

最後に、ページ側からコンポーネントを呼び出します。


```php:list.blade.php
<h1>コンテンツ一覧</h1>

{{ $contents_list->total() }}

  <div class="card">
  <table class="table">
  @foreach ($contents_list as $contents)
    <x-rows :contents="$contents"/>
  @endforeach
  </table>
  </div>

{{ $contents_list->links() }}
```

今回は、主に表示側の分割をコンポーネント側で行ってみました。
次回は、ロジックの分割をBladeのコンポーネントの機能を使って行ってみたいと思います。