ルーティングで使われるmidleware
とは何かについて。
▼例
Route::middleware(['first', 'second'])->group(function () {
Route::get('/', function () {
//省略
});
Route::group(['middleware' => 'auth.very_basic'], function () {
Route::get('/', function () {
//省略
});
ミドルウェアとは何か?
HTTPリクエスト(またはレスポンス)をチェックする機能のこと。
middlewareは自分で関数を定義して作成できる。
▼用途
- 指定した変数が条件を満たしているか
- 認証ユーザーかどうか
など、、
フローで見るMiddleware
▼通常のフロー
HTTP Request
↓
Route
↓
Controller
↓
View(Application)
↓
Response
▼ミドルウェアがある場合
HTTP Request
↓
Route
↓
**Before Middleware**
↓
Controller
↓
View(Application)
↓
**After Middleware**
↓
Response
・Before Middleware:リクエストをチェックする機能
・Afrter Middleware:レスポンスをチェックする機能
ミドルウェアは複数設置可能。
参考:midium.com
Middlewareを実際に使うまでの流れ
Middlewareを実際に使用するまでには大きく3つのステップがある。
1. ミドルウェアの作成(条件ファイルの作成)
2. ミドルウェアの登録
3. ミドルウェアをルートに適用
ミドルウェアの作成(条件ファイルの作成)
artisanコマンドの、make:middlewareで生成できる。
・php artisan make:middleware ミドルウェア名
$ php artisan make:middleware test
Middleware created successfully.
▼保存場所app > HTTP > Middleware > ミドルウェア名.php
Middlewareの中身
作成したミドルウェアの中身は以下のようになっている。
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class test
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
return $next($request);
}
}
・namespace App\Http\Middleware;
app > HTTP > Middlewareに保存されるので、名前空間も対応している。
・use Closure;
Closureクラスをインポート。
Clouseクラスとは何か?
無名関数と呼ぶ。https://www.php.net/closure
ここでは、次の処理に進める変数$next
を使えるようにしている。
・use Illuminate\Http\Request;
Laravelのコンポーネントである、Requestクラスをインポート。
・説明文(PHPDocs)
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
受け取ったrequestを処理する。
@param
: パラメータの説明
ここでは、$request
と$next
を使っていますという説明。参照元のクラスが示してある。@return
: 戻り値
ここでは、戻り値の型はmixed(何でもとりうる)であることを示している。
処理内容
functionにミドルウェアの処理を記述する。
public function handle(Request $request, Closure $next)
{
//処理
return $next($request);
}
return $next($request);
リクエストを次のステップに進めるという意味。
他にミドルウェアが設定されてない場合は、リクエストがコントローラーに渡される。
ミドルウェアの条件作成
実際にミドルウェアの条件部分を作ってみる。
Before Middlewareの作成
requestに対して実行するBefore Middlewareの実例。
class BeforeMiddleware
{
public function handle($request, Closure $next)
{
if ($request->age >= 50) {
return redirect('home');
}
return $next($request);
}
}
requestで渡されたデータageの値が50を超えている場合は、ルート名homeにリダイレクトする。
50以下の場合は次の処理に進む。
After MiddleWare
responseに対して実行するAfter Middlewareの実例。
class AfterMiddleware
{
public function handle($request, Closure $next)
{
$response = $next($request);
if ($response->age >= 50) {
return redirect('home');
}
return $response;
}
}
Before MiddlewareとAfter Middlewareの違い
▼Before Middleware
$request
に対して条件を指定return $next($request);
を返す(通常の処理)
▼After Middleware
$response = $next($request);
に対して条件を指定return $response;
を返す(通常の処理)
ミドルウェアの登録
ミドルウェアをルートに登録する方法は3つある。
- グローバル登録
- ルート登録
- グループ登録
ルート全体に通すか、個別にルートを指定するか、複数のミドルウェアをまとめて登録するかの違い。
いずれもApp\Http\Kernel
クラスの中に記述する。(デフォルトでミドルウェアが登録されている。)
グローバル登録
すべてのルートにミドルウェアを適用するには、app/Http/Kernel.phpの$middleware
プロパティに追加する。
・protected $middleware = [ ];
protected $middleware = [
// \App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\TrustProxies::class,
\Fruitcake\Cors\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
ルート登録
各ルートに個別にミドルウェアを適用するには、app/Http/Kernel.phpの$routeMiddleware
プロパティに追加する。
protected $routeMiddleware = [ 'ミドルウェア名' => 完全な名前空間::class];
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];
グループ登録
ミドルウェアをひとまとめにして適用するには、app/Http/Kernel.phpの$middlewareGroups
プロパティに追加する。
protected $middlewareGroups = [
'グループミドルウェア名' => [
完全な名前空間::class,
,,,,
];
デフォルトでミドルウェア名webとapiが用意されている。(webはURIに、apiはAPIルートに適用する目的)
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' => [
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
ミドルウェアをルートに適用
ルート登録したミドルウェア
$routeMiddleware
をルートに適用する方法。
・->middleware('ミドルウェア名', 'ミドルウェア名',,,)
▼一つだけ適用する場合
Route::get('admin/profile', function () {
//
})->middleware('auth');
URIにadmin/profileが入力された時、ミドルウェアauthを実行数する。
▼複数適用する場合
Route::get('/', function () {
//
})->middleware('first', 'second');
ホームディレクトリにアクセスした場合に、ミドルウェアfirstとsecondを実行する。
▼名前空間で指定
ミドルウェア名ではなく、名前空間で指定もできる。
use App\Http\Middleware\CheckAge;
Route::get('admin/profile', function () {
//
})->middleware(CheckAge::class);
グループ登録したミドルウェア
ルート登録した場合と同じように名前で指定できる。
Route::get('/', function () {
//
})->middleware('web');
グループ化したルートにミドルウェアを適用する
冒頭のRoute::middleware
や、Route::group(['middleware' => 'auth.very_basic']
などの表記について。これらが何をやっているか。
Route::middleware
これまでの->middleware
を冒頭で呼び出している。後ろにグループ化したルートがくる場合に使われる。
・Route::middleware('ミドルウェア名')->group()
後ろに続くグループ全体にミドルウェアを適用する。
Route::middleware(['web'])->group(function () {
//
});
Route::group(['middleware' => 'ミドルウェア名'], function(){ ルート });
groupメソッドの引数で適用するmiddlewareを指定している。
Route::group(['middleware' => 'auth.very_basic'], function () {
Route::get('/', ['as' => 'top', 'uses' => 'TopController@index']);
Route::get('privacy', 'PrivacyController@index')->name('privacy');
Route::get('optout', 'OptoutController@index')->name('optout');
});
(補足)auth.very_basic
Laravel標準のauth.basicとは違い、実際のデータベースの情報を使うことなくBasic認証を追加するミドルウェア。
>https://github.com/olssonm/l5-very-basic-auth/blob/master/README.jp.md