Laravel 学習(viewおさらい)

## 内容

以前viewについて学習したのですが下記内容がややこしかったのでおさらいです。

- @section・@yeild・@extends
- @component・@slot
- @include
- ビューコンポーザ

## 実行結果

以降に記述しているデフォルトや@section、@componentなどいずれも下図の結果になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604560/a9e8a316-3025-232f-0d8e-c54345e72f16.png)

## 共通処理

``` php:\routes\web.php
Route::get('/hello','App\Http\Controllers\HelloController@index');
```

## デフォルト

継承などせずに、コントローラとビューだけで解決します。

```php:\app\Http\Controllers\HelloController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\Response;

class HelloController extends Controller
{
    public function index() {
        $data = [
            'msg1'=>'MSG1', 
            'msg2'=>'MSG2'
        ];
        return view('hello.index', $data);
    }
}
```

```php:\resources\views\hello\index.blade.php
<html>
<head>
  <title>タイトル</title>
</head>
<body>
  <h1>タイトル</h1>
  <hr size="1">
  <h2 class="menutitle">メニュー</h2>
  <ul>
    <li>親1</li>
    <li>showの値</li>
    <li>子</li>
    <li>親2</li>
  </ul>
  <hr size="1">
  <div class="content">
    <p>コンテンツ</p>
    <p>何か記述する</p>   
    <p>msg1: {{$msg1}}</p>
    <p>msg2: {{$msg2}}</p>
  </div>
  <hr size="1">
  <div class="footer">
    <h2>フッター</h2>
    <p>フッターを記載します。</p>
  </div>
</body>
</html>
```

## @section・@yeild・@extends

子は@extendsにより親のレイアウトを継承します。
親が@yeild、子が@sectionとすることで同じ名前のもので紐づき、値が渡されます。
子が@parent、親が@sectionとすることで親の@sectionを上書きできます。

例：ヘッダーやフッター、サイドバーなどの共通レイアウトを持つテンプレートを作成し、各テンプレートで継承することで一貫したデザインを保ちながら異なるコンテンツを表示できます。

``` php:\app\Http\Controllers\HelloController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\Response;

class HelloController extends Controller
{
    public function index() {
        $data = [
            'msg1'=>'MSG1', 
            'msg2'=>'MSG2'
        ];
        return view('hello.index', $data);
    }
}
```

``` php:\resources\views\layouts\helloapp.blade.php(親)
<html>
<head>
  <title>@yield('title')</title>
</head>
<body>
  <h1>@yield('title')</h1>
  <hr size="1">
  @section('menubar')
  <h2 class="menutitle">メニュー</h2>
  <ul>
    <li>親1</li>
    <li>@show</li>
    <li>親2</li>
  </ul>
  <hr size="1">
  <div class="content">
    @yield('content')
  </div>
  <hr size="1">
  <div class="footer">
    @yield('footer')
  </div>
</body>
</html>
```

``` php:\resources\views\hello\index.blade.php(子)
@extends('layouts.helloapp')

@section('title', 'タイトル')

@section('menubar')
   @parent
   showの値
   <li>子</li>
@endsection

@section('content')
   <p>コンテンツ</p>
   <p>何か記述する</p>
   
   <p>msg1: {{$msg1}}</p>
   <p>msg2: {{$msg2}}</p>
@endsection

@section('footer')
   <h2>フッター</h2>
   <p>フッターを記載します。</p>
@endsection
```

## @component・@slot

@componentにより指定のビューに記載されたレイアウトを反映させます。
@slotを使うことで値部分だけは動的に変えるということができます。
小さなUI(ボタン、カード、アラート)などを再利用するのに適しています。

``` php:\app\Http\Controllers\HelloController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\Response;

class HelloController extends Controller
{
    public function index() {
        $data = [
            'msg1'=>'MSG1'
        ];
        return view('hello.index', $data);
    }
}
```

``` php:\resources\views\hello\index.blade.php(親)
@extends('layouts.helloapp')

@section('title', 'タイトル')

@section('menubar')
   @parent
   showの値
   <li>子</li>
@endsection

@section('content')
   <p>コンテンツ</p>
   <p>何か記述する</p>
   
   <p>msg1: {{$msg1}}</p>
   @component('components.message')
      @slot('msg')
         MSG2
      @endslot
   @endcomponent
@endsection

@section('footer')
   <h2>フッター</h2>
   <p>フッターを記載します。</p>
@endsection
```

``` php:\resources\views\layouts\helloapp.blade.php(子)
<html>
<head>
  <title>@yield('title')</title>
</head>
<body>
  <h1>@yield('title')</h1>
  <hr size="1">
  @section('menubar')
  <h2 class="menutitle">メニュー</h2>
  <ul>
    <li>親1</li>
    <li>@show</li>
    <li>親2</li>
  </ul>
  <hr size="1">
  <div class="content">
    @yield('content')
  </div>
  <hr size="1">
  <div class="footer">
    @yield('footer')
  </div>
</body>
</html>
```

``` php:\resources\views\components\message.blade.php
<p>msg2: {{$msg}}</p>
```

## @include

サブビューといいます。
他のビューをそのままテンプレートに挿入するために使用します。
ヘッダーやフッターなどの共通レイアウトのテンプレートを用意して読み込みます。
値を渡すことも可能ですが、静的なコンテンツに適しています。

``` php:\app\Http\Controllers\HelloController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\Response;

class HelloController extends Controller
{
    public function index() {
        $data = [
            'msg1'=>'MSG1'
        ];
        return view('hello.index', $data);
    }
}
```

``` php:\resources\views\hello\index.blade.php(親)
@extends('layouts.helloapp')

@section('title', 'タイトル')

@section('menubar')
   @parent
   showの値
   <li>子</li>
@endsection

@section('content')
   <p>コンテンツ</p>
   <p>何か記述する</p>
   
   <p>msg1: {{$msg1}}</p>
   @include('components.message', ['msg'=>'MSG2'])
@endsection

@section('footer')
   <h2>フッター</h2>
   <p>フッターを記載します。</p>
@endsection
```

``` php:\resources\views\layouts\helloapp.blade.php(子)
<html>
<head>
  <title>@yield('title')</title>
</head>
<body>
  <h1>@yield('title')</h1>
  <hr size="1">
  @section('menubar')
  <h2 class="menutitle">メニュー</h2>
  <ul>
    <li>親1</li>
    <li>@show</li>
    <li>親2</li>
  </ul>
  <hr size="1">
  <div class="content">
    @yield('content')
  </div>
  <hr size="1">
  <div class="footer">
    @yield('footer')
  </div>
</body>
</html>
```

``` php:\resources\views\components\message.blade.php
<p>msg2: {{$msg}}</p>
```

## ビューコンポーザ

ビューがレンダリングされる前に、そのビューに必要なデータを提供するために使用します。これにより、特定のビューで毎回必要なデータを一元管理することができます。
サイドバーなどにユーザ情報を表示させる場合に便利です。

``` php:\app\Http\Controllers\HelloController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\Response;

class HelloController extends Controller
{
    public function index() {
        $data = [
            'msg1'=>'MSG1'
        ];
        return view('hello.index', $data);
    }
}
```

``` php:\resources\views\hello\index.blade.php(親)
@extends('layouts.helloapp')

@section('title', 'タイトル')

@section('menubar')
   @parent
   showの値
   <li>子</li>
@endsection

@section('content')
   <p>コンテンツ</p>
   <p>何か記述する</p>
   
   <p>msg1: {{$msg1}}</p>
   <p>msg2: {{$msg2}}</p>
@endsection

@section('footer')
   <h2>フッター</h2>
   <p>フッターを記載します。</p>
@endsection
```

``` php:\resources\views\layouts\helloapp.blade.php(子)
<html>
<head>
  <title>@yield('title')</title>
</head>
<body>
  <h1>@yield('title')</h1>
  <hr size="1">
  @section('menubar')
  <h2 class="menutitle">メニュー</h2>
  <ul>
    <li>親1</li>
    <li>@show</li>
    <li>親2</li>
  </ul>
  <hr size="1">
  <div class="content">
    @yield('content')
  </div>
  <hr size="1">
  <div class="footer">
    @yield('footer')
  </div>
</body>
</html>
```

``` php:\app\Http\Composers\HelloComposer.php
<?php
namespace App\Http\Composers;

use Illuminate\View\View;

class HelloComposer
{
  public function compose(View $view) {
    $view->with('msg2', 'MSG2');
  }
}
```

``` php:\app\Providers\HelloServiceProvider.php
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\View;
use Symfony\Component\CssSelector\Node\FunctionNode;

class HelloServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     */
    public function register(): void
    {
        //
    }

    /**
     * Bootstrap services.
     */
    public function boot(): void
    {
        View::composer(
            'hello.index', 'App\Http\Composers\HelloComposer'
        );
    }
}
```

``` php:\bootstrap\providers.php
<?php

return [
    App\Providers\AppServiceProvider::class,
    App\Providers\HelloServiceProvider::class,
];
```

## まとめ

- 継承
サイト全体の共通レイアウトを定義し、個別ページで内容を上書きするために使用します。
- コンポーネント
再利用可能なUI要素を定義し、複数の場所で同じ構造や機能を使いたい場合に使用します。
- インクルード
部分的なテンプレートを別ファイルに切り出し、他のビューで再利用するために使用します。主に静的コンテンツに適しています。
- ビューコンポーザ
特定のビューがレンダリングされる前に、ビューに対して共通のデータを提供するために使用します。