Laravel 8.x ミドルウェア

イントロダクション

ミドルウェアは、アプリケーションに入るHTTPリクエストを検査およびフィルタリングするための便利なメカニズムを提供します。たとえば、Laravelには、アプリケーションのユーザーが認証されていることを確認するミドルウェアが含まれています。ユーザーが認証されていない場合、ミドルウェアはユーザーをアプリケーションのログイン画面にリダイレクトします。逆に、ユーザーが認証されている場合、ミドルウェアはリクエストをアプリケーションへ進めることを許可します。

ミドルウェアを追加して、認証以外にもさまざまなタスクを実行できます。たとえば、ログミドルウェアなら、アプリケーションが受信したすべてのリクエストをログへ記録できるでしょう。Laravelフレームワークには、認証やCSRF保護用のミドルウェアなど、ミドルウェアがいくつか含まれています。これらのミドルウェアはすべて、app/Http/Middlewareディレクトリにあります。

ミドルウェアの定義

新しいミドルウェアを作成するには、make:middleware Artisanコマンドを使用します。

php artisan make:middleware EnsureTokenIsValid

このコマンドは、新しいEnsureTokenIsValidクラスをapp/Http/Middlewareディレクトリ内に配置します。例としてこのミドルウェアで、リクエストが供給するtoken入力が、指定値と一致する場合にのみ、ルートへのアクセスを許可します。それ以外の場合は、ユーザーをhome URIへリダイレクトしましょう。

<?php

namespace App\Http\Middleware;

use Closure;

class EnsureTokenIsValid
{
    /**
     * 受信リクエストの処理
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if ($request->input('token') !== 'my-secret-token') {
            return redirect('home');
        }

        return $next($request);
    }
}

ご覧のとおり、与えられたtokenがシークレットトークンと一致しない場合、ミドルウェアはHTTPリダイレクトをクライアントに返します。それ以外の場合、リクエストはさらにアプリケーションに渡されます。リクエストをアプリケーションのより深いところに渡す(ミドルウェアが「パス」できるようにする)には、$requestを使用して$nextコールバックを呼び出す必要があります。

ミドルウェアは、HTTPリクエストがアプリケーションに到達する前に通過しなければならない一連の「レイヤー」として考えるのがベストです。各レイヤーはリクエストを検査したり、完全に拒否したりすることができます。

Tip!! すべてのミドルウェアはサービスコンテナを介して依存解決されるため、ミドルウェアのコンストラクター内で必要な依存関係をタイプヒントで指定できます。

ミドルウェアとレスポンス

もちろん、ミドルウェアはアプリケーションのより深部へリクエストの処理を委ねるその前後にあるタスクを実行できます。たとえば、次のミドルウェアは、リクエストがアプリケーションによって処理される前にいくつかのタスクを実行します。

<?php

namespace App\Http\Middleware;

use Closure;

class BeforeMiddleware
{
    public function handle($request, Closure $next)
    {
        // アクションの実行…

        return $next($request);
    }
}

一方、このミドルウェアは、リクエストがアプリケーションによって処理された後にそのタスクを実行します。

<?php

namespace App\Http\Middleware;

use Closure;

class AfterMiddleware
{
    public function handle($request, Closure $next)
    {
        $response = $next($request);

        // アクションの実行…

        return $response;
    }
}

ミドルウェアの登録

グローバルミドルウェア

アプリケーションへのすべてのHTTPリクエスト中であるミドルウェアを実行する場合は、app/Http/Kernel.phpクラスの$middlewareプロパティにそのミドルウェアクラスをリストします。

ルートに対するミドルウェアの指定

ミドルウェアを特定のルートに指定したい場合は、最初にアプリケーションのapp/Http/Kernel.phpファイルでミドルウェアにキーを割り当てる必要があります。デフォルトでは、このクラスの$routeMiddlewareプロパティには、Laravelに含まれているミドルウェアのエントリが含まれています。このリストへ独自のミドルウェアを追加して、選択したキーを割り当てることができます。

// App\Http\Kernelクラス内…

protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
    'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
    'can' => \Illuminate\Auth\Middleware\Authorize::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
    'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];

ミドルウェアがHTTPカーネルで定義されたら、middlewareメソッドを使用してミドルウェアをルートに割り当てることができます。

Route::get('/profile', function () {
    //
})->middleware('auth');

ミドルウェア名の配列をmiddlewareメソッドに渡すことにより、ルートに複数のミドルウェアを割り当てることができます。

Route::get('/', function () {
    //
})->middleware(['first', 'second']);

ミドルウェアを割り当てるときに、完全修飾クラス名を渡すこともできます。

use App\Http\Middleware\EnsureTokenIsValid;

Route::get('/profile', function () {
    //
})->middleware(EnsureTokenIsValid::class);

除外ミドルウェア

ミドルウェアをルートのグループに割り当てる場合、あるミドルウェアをグループ内の個々のルートに適用しないようにする必要が起きることもあります。これは、withoutMiddlewareメソッドを使用して実行できます。

use App\Http\Middleware\EnsureTokenIsValid;

Route::middleware([EnsureTokenIsValid::class])->group(function () {
    Route::get('/', function () {
        //
    });

    Route::get('/profile', function () {
        //
    })->withoutMiddleware([EnsureTokenIsValid::class]);
});

また、ルート定義のグループ全体から特定のミドルウェアのセットを除外することもできます。

use App\Http\Middleware\EnsureTokenIsValid;

Route::withoutMiddleware([EnsureTokenIsValid::class])->group(function () {
    Route::get('/profile', function () {
        //
    });
});

withoutMiddlewareメソッドはルートミドルウェアのみを削除でき、グローバルミドルウェアには適用されません。

ミドルウェアグループ

複数のミドルウェアを1つのキーにグループ化して、ルートへの割り当てを容易にしたい場合もあるでしょう。これは、HTTPカーネルの$middlewareGroupsプロパティを使用して実現可能です。

最初からLaravelは、一般的にWebおよびAPIルートへ適用する可能性のあるミドルウェアを含んだwebおよびapiミドルウェアグループを用意しています。これらのミドルウェアグループは、アプリケーションのApp\Providers\RouteServiceProviderサービスプロバイダによって、対応するwebおよびapiルートファイル内のルートに自動的に適用されることに注意してください。

/**
 * アプリケーションのルートミドルウェアグループ
 *
 * @var array
 */
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,
    ],
];

ミドルウェアグループは、個々のミドルウェアと同じ構文を使用して、ルートとコントローラアクションに割り当てることができます。繰り返しますが、ミドルウェアグループを使用すると、より便利に一度に多くのミドルウェアをルートに割り当てられます。

Route::get('/', function () {
    //
})->middleware('web');

Route::middleware(['web'])->group(function () {
    //
});

Tip!! 最初から、webおよびapiミドルウェアグループは、App\Providers\RouteServiceProviderによってアプリケーションの対応するroutes/web.phpおよびroutes/api.phpファイルへ自動的に適用されます。

ミドルウェアの順序

まれに、ミドルウェアを特定の順序で実行する必要があるでしょうが、ルートに割り当てられたときにはミドルウェアの順序を制御できません。この場合、app/Http/Kernel.phpファイルの$middlewarePriorityプロパティを使用してミドルウェアの優先度を指定できます。このプロパティは、デフォルトではHTTPカーネルに存在していません。存在しない場合は、以下のデフォルト定義をコピーしてください。

/**
 * ミドルウェアの優先順位でソートされたリスト
 *
 * これにより、非グローバルミドルウェアは常に指定する順序で実行されます。
 *
 * @var string[]
 */
protected $middlewarePriority = [
    \Illuminate\Cookie\Middleware\EncryptCookies::class,
    \Illuminate\Session\Middleware\StartSession::class,
    \Illuminate\View\Middleware\ShareErrorsFromSession::class,
    \Illuminate\Contracts\Auth\Middleware\AuthenticatesRequests::class,
    \Illuminate\Routing\Middleware\ThrottleRequests::class,
    \Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class,
    \Illuminate\Session\Middleware\AuthenticateSession::class,
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
    \Illuminate\Auth\Middleware\Authorize::class,
];

ミドルウェアのパラメータ

ミドルウェアは追加のパラメータを受け取ることもできます。たとえば、アプリケーションが特定のアクションを実行する前に、認証済みユーザーが特定の「役割り(role)」を持っていることを確認する必要がある場合、追加の引数として役割名を受け取るEnsureUserHasRoleミドルウェアを作成できます。

追加のミドルウェアパラメータは、$next引数の後にミドルウェアに渡されます。

<?php

namespace App\Http\Middleware;

use Closure;

class EnsureUserHasRole
{
    /**
     * 受信リクエストの処理
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  string  $role
     * @return mixed
     */
    public function handle($request, Closure $next, $role)
    {
        if (! $request->user()->hasRole($role)) {
            // リダイレクト…
        }

        return $next($request);
    }

}

ミドルウェアのパラメータはルート定義時に、ミドルウェア名とパラメータを「:」で区切って指定します。複数のパラメーターはコンマで区切る必要があります。

Route::put('/post/{id}', function ($id) {
    //
})->middleware('role:editor');

終了処理ミドルウェア

HTTPレスポンスがブラウザに送信された後、ミドルウェアが何らかの作業を行う必要がある場合があります。ミドルウェアでterminateメソッドを定義し、WebサーバがFastCGIを使用している場合、レスポンスがブラウザに送信された後、terminateメソッドが自動的に呼び出されます。

<?php

namespace Illuminate\Session\Middleware;

use Closure;

class TerminatingMiddleware
{
    /**
     * 受信リクエストの処理
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        return $next($request);
    }

    /**
     * レスポンスがブラウザに送信された後にタスクを処理
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Illuminate\Http\Response  $response
     * @return void
     */
    public function terminate($request, $response)
    {
        // …
    }
}

terminateメソッドは、リクエストとレスポンスの両方を受信する必要があります。終了処理ミドルウェアを定義したら、それをapp/Http/Kernel.phpファイルのルートまたはグローバルミドルウェアのリストに追加する必要があります。

ミドルウェアでterminateメソッドを呼び出すと、Laravelはサービスコンテナからミドルウェアの新しいインスタンスを依存解決します。handleメソッドとterminateメソッドが呼び出されたときに同じミドルウェアインスタンスを使用する場合は、コンテナのsingletonメソッドを使用してミドルウェアをコンテナに登録します。通常、これはAppServiceProviderregisterメソッドで実行する必要があります。

use App\Http\Middleware\TerminatingMiddleware;

/**
 * 全アプリケーションサービスの登録
 *
 * @return void
 */
public function register()
{
    $this->app->singleton(TerminatingMiddleware::class);
}

ドキュメント章別ページ

ヘッダー項目移動

注目:アイコン:ページ内リンク設置(リンクがないヘッダーへの移動では、リンクがある以前のヘッダーのハッシュをURLへ付加します。

移動

クリックで即時移動します。

設定

適用ボタンクリック後に、全項目まとめて適用されます。

カラーテーマ
和文指定 Pagination
和文指定 Scaffold
Largeスクリーン表示幅
インデント
本文フォント
コードフォント
フォント適用確認

フォントの指定フィールドから、フォーカスが外れると、当ブロックの内容に反映されます。EnglishのDisplayもPreviewしてください。

フォント設定時、表示に不具合が出た場合、当サイトのクッキーを削除してください。

バックスラッシュを含むインライン\Code\Blockの例です。

以下はコードブロックの例です。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * ユーザに関連する電話レコードを取得
     */
    public function phone()
    {
        return $this->hasOne('App\Phone');
    }
}

設定を保存する前に、表示が乱れないか必ず確認してください。CSSによるフォントファミリー指定の知識がない場合は、フォントを変更しないほうが良いでしょう。

キーボード・ショートカット

オープン操作

PDC

ページ(章)移動の左オフキャンバスオープン

HA

ヘッダー移動モーダルオープン

MS

移動/設定の右オフキャンバスオープン

ヘッダー移動

T

最初のヘッダーへ移動

E

最後のヘッダーへ移動

NJ

次ヘッダー(H2〜H4)へ移動

BK

前ヘッダー(H2〜H4)へ移動

その他

?

このヘルプページ表示
閉じる