【Laravel】ルーティングのミドルウェアとは何か?使い方を実例で解説 |Route::midlewareの意味、BeforeとAfter Middlewareの違い

laravel-prograshi(プロぐらし) Laravel
記事内に広告が含まれていることがあります。

ルーティングで使われる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つある。

  1. グローバル登録
  2. ルート登録
  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');
});

(参考)groupメソッドとは何か?


(補足)auth.very_basic

Laravel標準のauth.basicとは違い、実際のデータベースの情報を使うことなくBasic認証を追加するミドルウェア。


https://github.com/olssonm/l5-very-basic-auth/blob/master/README.jp.md


タイトルとURLをコピーしました