日記

日々のことと、Python/Django/PHP/Laravel/nodejs などソフトウェア開発のことを書き綴ります

Laravel 5.1 入門記 その4(Middleware 編)

今回は middleware について。

laravel.com

Introduction

middleware はアプリケーションにリクエストが届く手前でフィルタリングするような処理を実装できるとのこと。例えば認証とか、ロギングとか…。 前回の CSRF Protection で出て来た CSRF トークンをチェックする処理も middleware として実装されていると書かれてました。

middleware は app/Http/Middleware ディレクトリに置かれるらしい。

Defining Middleware

Middleware は、 artisan コマンドでベースを生成できるらしい。 artisan は Django manage.py みたいなものっぽい。早速作ってみます。

$ php ./artisan make:middleware OldMiddleware
Middleware created successfully.
$ ls ./app/Http/Middleware/
Authenticate.php  EncryptCookies.php  OldMiddleware.php  RedirectIfAuthenticated.php  VerifyCsrfToken.php

できていた。OldMiddleware.php の中を見ると

$ cat ./app/Http/Middleware/OldMiddleware.php 
<?php

namespace App\Http\Middleware;

use Closure;

class OldMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        return $next($request);
    }
}

至ってシンプル。 handle に実装を書けば良さそうです。 何となく書かれてしまっているけど、 $next($request) を呼ぶと、リクエストがアプリケーション側のコードに送られます。

    public function handle($request, Closure $next)
    {
        // アプリケーションの処理前に行う処理
        $response = $next($request);
        // アプリケーションの処理後に行う処理
        return $response
    }

分解すると上記のような形になって、アプリケーションの処理の前後に何らかの処理を挟み込めます。

Registering Middleware

作った middleware は作っただけでは Laravel の動作上認識されず、 app/Http/Kernel.php に登録する必要があるらしい。

Middlewareの登録は グローバルレベルのものと、routes.php に必要であれば登録するものに分類できて、 Kernel.php への登録方法が異なるらしい。

app/Http/Kernel.php の中身を見てみます。

$ cat app/Http/Kernel.php 
<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    /**
     * The application's global HTTP middleware stack.
     *
     * @var array
     */
    protected $middleware = [
        \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
    ];

    /**
     * The application's route middleware.
     *
     * @var array
     */
    protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    ];
}

$middleware に設定するのはグローバルレベルで強制実行される middlewareで、$routeMiddleware に設定するのは routes.php で任意に設定可能な middleware となるようです。

routes.php で middleware を設定するときは、こんな感じで設定するらしい。

Route::get('admin/profile', ['middleware' => 'auth', function () {
    //
}]);

Middleware Parameters

ミドルウェアに対して、外側からパラメータを与えて挙動を変えたい時に使用するための仕組みらしい。

例えば、 権限チェックを行うミドルウェアを作ったとして、ログインしているユーザが XXXX な権限を持っているかを、 routes.php からパラメータを与えて設定を行ったりするようだ。

具体的な設定方法は、まず middleware の handler メソッドに対して引数 ($rolename) を追加する。

public function handle($request, Closure $next, $rolename)

そして、Kernel.php に 'role' として登録します。(権限チェックの middleware なので) 続いて、 routes.php で適用する時は以下の様に設定する。

Route::put('post/{id}', ['middleware' => 'role:edit', function ($id) {
    //
}]);

こんな感じです。role:edit の部分がポイントで、コロンで区切って引数を指定するらしい。複数引数も指定出来て、 role:edit1,edit2 のような設定方法になるらしい。

うーん、もうちょっと何とかならなかったのかな、という印象が…。

Terminable Middleware

レスポンスを返した後に処理を追加したい場合に使う middleware で、handle メソッドではなく、 terminate メソッドに実装を行う。terminate メソッドは $request と $response を受け取ります。

Terminatable Middleware はセッション保存などに使われているらしい。

あんまり使うことは無いかなぁと言う印象。ちなみに Terminable Middleware は、グローバルレベルのミドルウェアとして登録するらしい。

このセクションはあまり手を動かさずに読み進めた感じ。次に行きます。