ミドルウェアとは
リクエストを受け取るとコントローラ処理の前後に割り込み、
独自の処理を追加する仕組みこと。
コントローラは、
「特定のアドレスにアクセスがあると、Larabelはルート情報をもとに、
指定のコントローラのアクションを呼び出す」役割がありますが、
全てのアクセス時に何かの処理をしておくとなると、
処理に負荷がかかったり何かと面倒。
そこで、「特定のアドレスにリクエストが送られたら、
自動的に何かしら処理を行う。」という仕組みを用意しました。
それが「ミドルウェア」です。
特徴として、コントローラの処理に影響されない。
handleメソッド
Midllewareクラスには、1つだけメソッドが用意されています。
「handle」といういうクラスです。
public function handle(Request $request, Closure $next)
{
return $next($request);
}
第一引数の「$request
」はリクエスト情報を管理するRequestクラスのインスタンスで、
第二引数の「$next
」は、Closureクラスのインスタタンスです。
ここで渡された「$next
」はクロージャになっており、
これを呼び出して実行s9うることで、ミドルウェアからアプリケーションへと
送られるリクエスト(Requestインスタンス)を作成することができます。
ミドルウェアを修正する
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の値)に
新たな値を追加するものです。
記述したら、カーネルに追加したいミドルウェアを登録する。
protected $routeMiddleware = [
**省略**
'hello' => App\Http\Middleware\HelloMiddleware::class,
];
ミドルウェアの実行
作成されたミドルウェアは、それだけであhまだ利用することが「できません。
これを使うには、「利用するミドルウェアを呼び出す処理」の追加必要。
ミドルウェアの呼び出し処理を追記
use App\Http\Middleware\HelloMiddleware;
Route::get('hello','App\Http\Controllers\HelloController@index')
->middleware(HelloMiddleware::class);
複数のミドルウェアを利用したい場合は、
メソッドチェーンとして連続してミドルウェアの処理を追加することができます。
oute::get(**ルーティング**)
->middleware(**クラス名**)->middleware(**クラス名**)->middleware(**クラス名**);
ビューとコントローラの修正
@section('content')
<p>ここが本文のコンテンツです。</p>
<table>
@foreach($data as $item)
<tr><th>{{$item['name']}}</th><td>{{$item['mail']}}</td></tr>
@endforeach
</table>
@endsection
class HelloController extends Controller
{
public function index(Request $request) {
return view('hello.index',['data'=>$request->data]);
}
}
<ミドルウェアの作成から利用までの手順>
①ミドルウェアを作成する。
②作成したミドルウェアをカーネルに登録する。
③利用するミドルウェアを呼び出す処理を追記する
リクエストとレスポンス
<リクエストが送られてきてからクライアントにレンポンスが返されるまでの流れ>
①リクエストが送られる
②ミドルウェアのhandleが呼び出される
③$next
を実行する。
(他にミドルウェアがなければ、コントローラにあるアクションが呼び出される)
④アクションメソッドが終わると、レスポンスが生成される。
(この生成されたレスポンスが$next
の戻り値として返される。)
⑤返されたレスポンスが、returnとして返され、クライアントに返送される。
前処理と後処理
前処理
public function handle(Request $request, Closure $next)
{
**処理を実行する**
return $next($request);
}
後処理
public function handle(Request $request, Closure $next)
{
$response = $next($request);
**処理を実行する**
return $response;
}
レスポンスを操作する
レスポンスを操作するために、
ミドルウェアを下記のようにk修正する。
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;
}
それぞれの処理
$response = $next($request);
$next
を実行し、その結果を$response
に代入する。
$content = $response->content();
レスポンスから返送されコンテンツを取得します。
また取得したHTMLソースコードを正規表現で痴漢します。
$pattern = '/<middle>(.*)<\/middle>/i';
$replace = '<a herf="http://$1">$1</a>';
$content = preg_replace($pattern, $replace, $content);
これは、<middle></middle>
を''というテキストに
置換する処理です。
あとは、レスポンスにコンテンツを設定し、returnするだけです。
$response->setContent($content);
return $response;
レスポンスへのコンテンツ設定は'setContent()'メソッドを使います。
<上手く挙動しなかったので、復習要>
グローバルミドルウェア
全てのアクセスで自動的にミドルウェアが事項できるようにしたい場合は、
「グローバルミドルウェア」を使用する。
protected $middleware = [
**グローバルミドルウェアに追記**
App\Http\Middleware\HelloMiddleware::class,
];
上記の記述をすることで、
指定のミドルウェアがグローバル(どこにアクセスしても実行する)ミドルウェアとして登録できる。
Route::get('hello','App\Http\Controllers\HelloController@index');
これにより、ルーティング情報にHelloにアクセスがあれば、
ミドルウェアを実行するという記述を削除しても、
ミドルウェアが実行される。
ミドルウェアのグループ化
多数のミドルウェアを使うようになると、
複数のミドルウェアを1つにまとめて扱えるようになれば、管理も楽になる。
その場合は、ミドルウェアのグループ化して登録するための仕組みみ用意されている。
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'
がグループ名になります。
ミドルウェアグループの登録
rotected $middlewareGroups = [
'hello' => [
\App\Http\Middleware\HelloMiddleware::class,
],
];
'hello'
グループを追加し、HelloMiddleware
をグループに登録しました。
先ほど登録したグローバルミドルウェアからは削除します。
Route::get('hello','App\Http\Controllers\HelloController@index')
->middleware('hello');
ルーティング情報に'hello'
グループのミドルウェアの処理を実行するように、
追記することでグループ登録したミドルウェアを実行することができます。