Chapter3　サービスとビューコンポーザ（3-5）

# サービスとビューコンポーザ

## ビューコンポーザーとは

コントローラから呼び出されたビューテンプレートをレンダリングする際に、
自動的に実行される処理を用意するための部品。

## サービスとサービスプロバイダ

**サービス**：機能強化のための仕組み。
**サービスコンテナ**：DIと呼ばれる機能を使ったシステムでLarabelの仕組み。

**DI（Dependency Injection）**：依存性注入

**サービスプロバイダ**：
サービスを登録するために用意されている部品で、
必要に応じて特定のサービスを組み込んで使えるようにするためのもの。

## サービスプロバイダの基本形

サービスプロバイダは`ServiceProvider`というクラスを継承して作成されます。

```ServiceProvider.php
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class HelloServiceProvider extends ServiceProvider
{
    public function register()
    {
        //
    }

    public function boot()
    {
        //
    }
}

```

サービスプロバイダは「ServiceProvider」というクラスを継承して作成される。
サービスプロバイダは２つのメソッドが用意されている。

- register　：サービスプロバイダの登録処理を行う。
- boot　　 ：サービスアプリケーションへのブートサトラップ処理を行う。
　　　　 （設定したビューをレンダリングする際に自動的にコンポーザを呼び出される。）


## サービスプロバイダを生成する

サービスプロバイダは「app」>「Providers」に格納されています。
直接作成することもできますが、
`php artisan`コマンドで簡単にサービスプロバイダを生成できるので、
今回はコマンドを使います。

`php artisan`コマンドの基本形
```
php artisan make:provider *サービスプロバイダ名*
```
`php artisan`コマンドを使って「HelloServiceProvider」を作成します。

```command
% php artisan make:provider HelloServiceProvider
Provider created successfully.
```
これで簡単にサービスプロバイダを生成することができます。


## ビューコンポーザを用意する

ビューコンポーザを用意すには２つの方法があります。

- ビューコンポーザのクラスの定義し、bootで登録する
- boot内に無名クラスでビューコンポーザの処理に組み込む

### クロージャー（無名関数）でコンポーザ処理を作る

#### View::composerについて

`View::composer`はサービスプロバイダに
ビューコンポーザを設定するためのメソッドになります。

`View::composer`は以下の構文で記述します。

```ServiceProvider.php
View::composer(*ビューの指定*, *関数又はクラス*);
```

```ServiceProvider.php
public function boot()
    {
        View::composer(
            'hello.index', function($view){
                $view->with('view_message', 'composer message!') ;
            }
        );
    }
```

上記の記述はサービスプロバイダにブートストラップ処理を登録するために、
指定のテンプレートをレンダリングした際に、
自動的に処理されるビューコンポーザを用意します。

記述内の`with('view_message', 'composer message!')`は、
ビュークラスのインスタンスです。

withの構文
```sample.php
$view->with(*変数名*, *値*) ;
```

## サービスプロバイダの登録

サービスプロバイダ（HelloServiceProvider）は完成しましたが、
今度は作成したサービスプロバイダをアプリケーションに登録する必要があります。

アプリケーションは「config」フォルダにある「app.php」に記述していくことになります。

```app.php
'providers' => [

        /*
         * Laravel Framework Service Providers...
         */
        Illuminate\Auth\AuthServiceProvider::class,
        Illuminate\Broadcasting\BroadcastServiceProvider::class,
        Illuminate\Bus\BusServiceProvider::class,
        **ここに追記する**
```

上記の場所に下記の記述を追記することで、
アプリケーションに作成したサービスプロバイダを登録できる。

```app.php
Illuminate\View\HelloServiceProvider::class,
```

## ビューコンポーザを利用する

ビューコンポーザを利用するために、「index.blade.php」を修正します。

```index.php
@section('content')

    <p>ここが本文のコンテンツです。</p>
    <p>
        Controller value<br>
        'message' = {{$message}}
    </p>
    <p>
        ViewComposer value<br>
        'view_message' = {{$view_message}}
    </p>

@endsection
```

ここで記述した際に、下記のエラー発生。

```
Class 'App\Providers\View' not found
```
下の記事を参考に「HelloServiceProvider.php」に
VIEWの使用宣言をしたら解決した。

```HelloServiceProvider.php
use Illuminate\Support\Facades\View;
```

https://qiita.com/yyy752/items/b4bfce77f5398dad5c4e

## ビューコンポーザクラスの作成

$viewはViewクラスのインスタンスで、
composerでwithメソッドを使ってviewに変数を渡すように、定義をする。

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

use Illuminate\View\View;

class HelloComposer
{

    public function compose(View $view) {

        $view->with('view_message', 'this view is"' .$view->getName() . '"!!' );

    }

}
```

サービスプロバイダをビューコンポーザを呼び出すように修正する。

```HelloServiceProvider.php
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\View;

class HelloServiceProvider extends ServiceProvider
{

    public function boot()
    {
        View::composer(
            'hello.index', 'App\Http\Composers\HelloComposer'
        );
    }

}
```

＜注意事項＞

ビューコンポーザからの処理はコントローラから見えないので、
コントローラで処理する必要があるものはビューコンポーザに用意するべきではない。

- 指定のビューでは常に該当の処理を行うか
- 他のビューで使用しない処理か

という２つの観点で、
1. コントローラに必要に応じて処理をさせるのか
1. ビューコンポーザに自動的に処理させるのか

を慎重に判断する必要がある。