Chapter4　ミドルウェアの利用（4-1）

# ミドルウェアとは

リクエストを受け取るとコントローラ処理の前後に割り込み、
独自の処理を追加する仕組みこと。

コントローラは、
「特定のアドレスにアクセスがあると、Larabelはルート情報をもとに、
指定のコントローラのアクションを呼び出す」役割がありますが、
全てのアクセス時に何かの処理をしておくとなると、
処理に負荷がかかったり何かと面倒。

そこで、「特定のアドレスに**リクエストが送られたら、**
自動的に何かしら処理を行う。」という仕組みを用意しました。

それが「ミドルウェア」です。
特徴として、コントローラの処理に影響されない。

# handleメソッド

Midllewareクラスには、１つだけメソッドが用意されています。
「handle」といういうクラスです。

```Midelleware.php
public function handle(Request $request, Closure $next)
    {
        return $next($request);
    }
```
第一引数の「`$request`」はリクエスト情報を管理するRequestクラスのインスタンスで、
第二引数の「`$next`」は、Closureクラスのインスタタンスです。

ここで渡された「`$next`」はクロージャになっており、
これを呼び出して実行s９うることで、ミドルウェアからアプリケーションへと
送られるリクエスト（Requestインスタンス）を作成することができます。


# ミドルウェアを修正する

```Midelleware.php
public function handle(Request $request, Closure $next)
    {

        $data = [
            ['name'=>'taro', 'mail'=>'taro@yamada'],
            ['name'=>'hanako', 'mail'=>'hanako@flower'],
            ['name'=>'sachiko', 'mail'=>'sachiko@happy'],
        ];

        $request->merge(['data'=>$data]);

        return $next($request);
    }

```

## 「merge」メソッド

```
request->merge(**配列**);
```

この「merge」メソッドは、フォームの送信などで送られる値（inputの値）に
新たな値を追加するものです。

記述したら、カーネルに追加したいミドルウェアを登録する。

```Kernel.php
protected $routeMiddleware = [
        
        **省略**        

        'hello' => App\Http\Middleware\HelloMiddleware::class,
    ];
```


# ミドルウェアの実行

作成されたミドルウェアは、それだけであhまだ利用することが「できません。
これを使うには、「利用するミドルウェアを呼び出す処理」の追加必要。


## ミドルウェアの呼び出し処理を追記


```web.php
use App\Http\Middleware\HelloMiddleware;

Route::get('hello','App\Http\Controllers\HelloController@index')
  ->middleware(HelloMiddleware::class);
```

複数のミドルウェアを利用したい場合は、
メソッドチェーンとして連続してミドルウェアの処理を追加することができます。

```sample.php
oute::get(**ルーティング**)
  ->middleware(**クラス名**)->middleware(**クラス名**)->middleware(**クラス名**);
```

## ビューとコントローラの修正

```index.php

@section('content')

    <p>ここが本文のコンテンツです。</p>
    <table>
        @foreach($data as $item)
            <tr><th>{{$item['name']}}</th><td>{{$item['mail']}}</td></tr>
        @endforeach
    </table>

@endsection


```

```HelloController.php
class HelloController extends Controller
{
    public function index(Request $request) {

        return view('hello.index',['data'=>$request->data]);

    }

}
```


## ＜ミドルウェアの作成から利用までの手順＞

①ミドルウェアを作成する。
②作成したミドルウェアをカーネルに登録する。
③利用するミドルウェアを呼び出す処理を追記する

# リクエストとレスポンス

## ＜リクエストが送られてきてからクライアントにレンポンスが返されるまでの流れ＞

①リクエストが送られる
②ミドルウェアのhandleが呼び出される
③`$next`を実行する。
　（他にミドルウェアがなければ、コントローラにあるアクションが呼び出される）
④アクションメソッドが終わると、レスポンスが生成される。
　（この生成されたレスポンスが`$next`の戻り値として返される。）
⑤返されたレスポンスが、returnとして返され、クライアントに返送される。

## 前処理と後処理


### 前処理
```sample.php
public function handle(Request $request, Closure $next)
    {
        **処理を実行する**

        return $next($request);
    }
```

### 後処理
```sample.php
public function handle(Request $request, Closure $next)
    {
        $response = $next($request);

　　　　　　　　　　　　　　　　　**処理を実行する**

        return $response;
    }

```

## レスポンスを操作する

レスポンスを操作するために、
ミドルウェアを下記のようにk修正する。

```HelloMiddleware.php

public function handle(Request $request, Closure $next)
    {

        $response = $next($request);
        $content = $response->content();

        $pattern = '/<middle>(.*)<\/middle>/i';
        $replace = '<a herf="http://$1">$1</a>';
        $content = preg_replace($pattern, $replace, $content);
        $response->setContent($content);

        return $response;
    }

```

## それぞれの処理

```sample.php
$response = $next($request);
```
`$next`を実行し、その結果を`$response`に代入する。

```sample.php
$content = $response->content();
```
レスポンスから返送されコンテンツを取得します。
また取得したHTMLソースコードを正規表現で痴漢します。

```sample.php
$pattern = '/<middle>(.*)<\/middle>/i';
$replace = '<a herf="http://$1">$1</a>';
$content = preg_replace($pattern, $replace, $content);
```
これは、`<middle></middle>`を'<a herf="http://"></a>'というテキストに
置換する処理です。
あとは、レスポンスにコンテンツを設定し、returnするだけです。

```sample.php
$response->setContent($content);
return $response;
```

レスポンスへのコンテンツ設定は'setContent()'メソッドを使います。

＜上手く挙動しなかったので、復習要＞


# グローバルミドルウェア

全てのアクセスで自動的にミドルウェアが事項できるようにしたい場合は、
「グローバルミドルウェア」を使用する。


```kernel.php
protected $middleware = [
        
        **グローバルミドルウェアに追記**
　　　　　　　　　　　　　　　　App\Http\Middleware\HelloMiddleware::class,
    ];

```

上記の記述をすることで、
指定のミドルウェアがグローバル（どこにアクセスしても実行する）ミドルウェアとして登録できる。

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

これにより、ルーティング情報にHelloにアクセスがあれば、
ミドルウェアを実行するという記述を削除しても、
ミドルウェアが実行される。


## ミドルウェアのグループ化

多数のミドルウェアを使うようになると、
複数のミドルウェアを１つにまとめて扱えるようになれば、管理も楽になる。

その場合は、ミドルウェアのグループ化して登録するための仕組みみ用意されている。

```web.php
protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            'throttle:api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
    ];
```

上記の`'web'`や`'api'` がグループ名になります。

### ミドルウェアグループの登録

```web.php
rotected $middlewareGroups = [
        'hello' => [
            \App\Http\Middleware\HelloMiddleware::class,
        ],
    ];

```
`'hello'`グループを追加し、`HelloMiddleware`をグループに登録しました。

先ほど登録したグローバルミドルウェアからは削除します。

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

ルーティング情報に`'hello'`グループのミドルウェアの処理を実行するように、
追記することでグループ登録したミドルウェアを実行することができます。