ミドルウェア
ミドルウェア
つまりコントローラの処理を一時【奪い取る】機能です。
作成方法は[artisan]コマンドを使うと楽チンで、以下のような書式となります。
php artisan make:middleware {ミドルウェア名} それでは名前を「Initialize」として作成してみましょう。
C:\~\laravel_12>php artisan make:middleware Initialize
INFO Middleware [C:\xampp\htdocs\main\laravel_12\app\Http\Middleware\Initialize.php] created successfully.
C:\~\laravel_12>
初期状態は以下の様になります。
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class Initialize {
public function handle(Request $request, Closure $next): Response {
return $next($request);
}
}
「~\routes\web.php」で設定します。
Route::group(['middleware' => 'App\Http\Middleware\Initialize::class'], function(){
Route::get('/hoge', [App\Http\Controllers\HogeController::class, 'index'])->name('hoge.index');
});
この様に、既存のルート設定をミドルウェア定義の中にポイっと入れるだけです。 この段階では画面にアクセスしても何も起こりません。
では先ほどの「Initialize.php」に以下コードを追記してみましょう。
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class Initialize {
public function handle(Request $request, Closure $next): Response {
var_dump("OK");exit;
return $next($request);
}
}
まさに「HogeController」の処理が奪われた事が理解できたと思います。 もう少しコードを変形させてみましょう。
以下の様にしてみてください。
⇒
$response = $next($request);
return $response;
そして「return $response;」で画面レンダリングをしています。
つまりコントローラ処理の【前後】をインターセプトする事が可能となります。 「Initialize」「HogeController」に『echo』を仕込むと処理の順番が確認できると思います。
複数のミドルウェアを使う
何個だっていけちゃいます。
試しに同じ内容のミドルウェア『Initialize_second.php』を作成し、それぞれ以下の様な「echo」を入れてみます。
class Initialize {
public function handle(Request $request, Closure $next): Response {
echo "Initialize [Start] ⇒ ";
$response = $next($request);
echo "Initialize [End] ⇒ ";
return $response;
}
}
class Initialize_second {
public function handle(Request $request, Closure $next): Response {
echo "Initialize_second [Start] ⇒ ";
$response = $next($request);
echo "Initialize_second [End] ⇒ ";
return $response;
}
}
public function index(Request $request) {
echo "HogeController ⇒ ";
~ 省略 ~
}
Route::group(
['middleware' => [
'App\Http\Middleware\Initialize::class',
'App\Http\Middleware\Initialize_second::class',
]
], function(){
Route::get('/hoge', [App\Http\Controllers\HogeController::class, 'index'])->name('hoge.index');
});
以下の様な出力になったハズです。
設定方法色々
この記述方法は、ほとんど全てのルートが同じミドルウェアに処理される場合はソースとして見やすいですが、
ルートによって様々なミドルウェアを使用する場合は、ちょっと見苦しいです。。 例えばミドルウェアが3個あり、以下の様な設定にした場合はどうでしょう?
Route::group(
['middleware' => [
'App\Http\Middleware\Initialize_aaa::class',
'App\Http\Middleware\Initialize_bbb::class',
'App\Http\Middleware\Initialize_ccc::class',
]
], function(){
Route::get('/hoge', [App\Http\Controllers\HogeController::class, 'hoge'])->name('hoge');
});
Route::group(
['middleware' => [
'App\Http\Middleware\Initialize_aaa::class',
'App\Http\Middleware\Initialize_bbb::class',
]
, function(){
Route::get('/foo', [App\Http\Controllers\HogeController::class, 'foo'])->name('foo');
});
Route::group(
['middleware' => [
'App\Http\Middleware\Initialize_aaa::class',
]
], function(){
Route::get('/bar', [App\Http\Controllers\HogeController::class, 'bar'])->name('bar');
});
ちょっと見づらくないですか? もし以下の様に記述できたらどうでしょう。
Route::get('/hoge', [App\Http\Controllers\HogeController::class, 'hoge'])->name('hoge')->middleware('M_abc');
Route::get('/foo', [App\Http\Controllers\HogeController::class, 'foo'])->name('foo')->middleware('M_ab');
Route::get('/bar', [App\Http\Controllers\HogeController::class, 'bar'])->name('bar')->middleware('M_a');
でも当然このままではエラーなので、「middleware」属性で設定した名前とミドルウェアをマッピングする必要があります。
「~\bootstrap\app.php」内の「withMiddleware」のクロージャ内に記述します。
~ 省略 ~
->withMiddleware(function (Middleware $middleware): void {
$middleware->appendToGroup('M_abc', [
App\Http\Middleware\Initialize_aaa::class,
App\Http\Middleware\Initialize_bbb::class,
App\Http\Middleware\Initialize_ccc::class,
]);
$middleware->appendToGroup('M_ab', [
App\Http\Middleware\Initialize_aaa::class,
App\Http\Middleware\Initialize_bbb::class,
]);
$middleware->appendToGroup('M_a', [
App\Http\Middleware\Initialize_aaa::class,
]);
})
~ 省略 ~
ルートの設定とミドルウェアの設定が分離できてスッキリしました。
最後に
ミドルウェアを使うと共通の処理をコントローラから分離ができるので色々なソースがスッキリしますね。
例えばアクセスログの出力なんかうってつけです。
また、認証の独自カスタマイズをしてきましたが、カスタマイズできてない場所が1つありました。 それがまさに『Route::group(['middleware' => 'auth'], function(){』の部分です。
Laravelの組込みミドルウェアを認証制御に使っていましたが、
この機能は単純に非認証状態なら任意の画面にリダイレクトする程度です。 こんなの先ほど作成した「Initialize.php」に組み込んじゃえば良いのです!!




