LaravelでMiddlewareの実行順序を設定する

LaravelでMiddlewareの実行順序を指定する方法についてです。検索してもやり方が見つからなかったので、比較的新しいバージョンからできるようになったのかもしれません。意外と簡単です。

Kernelで$middlewarePriorityを指定するだけ

app/Http/Kernel.phpIlluminate\Foundation\Http\Kernelを継承していますが、この親クラスに下記のメンバーがあります。

    protected $middlewarePriority = [
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \Illuminate\Auth\Middleware\Authenticate::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
        \Illuminate\Auth\Middleware\Authorize::class,
    ];

この$middlewarePriorityというメンバー変数をapp/Http/Kernel.phpでオーバーライドして指定するだけです。たとえば下記のような感じです。

    protected $middlewarePriority = [
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \Illuminate\Auth\Middleware\Authenticate::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
        \Illuminate\Auth\Middleware\Authorize::class,

        // 下記を追加
        \App\Http\Middleware\Hoge::class,
        \App\Http\Middleware\Hoge::class . ':param1',
        \App\Http\Middleware\Moge::class,
    ];

これだけでした。

ちなみにこの配列を利用しているのは、Illuminate\Routing\RoutersortMiddlewareメソッドです。

パラメーターを指定している場合は注意

Controller側でMiddlewareを指定する場合パラメーター付きで指定している事があると思います。たとえば下記のような感じ。

    public function __construct()
    {
        $this->middleware('home:param1');
    }

パラメーターがついている場合、パラメーター付きの名称が$middlewarePriorityに指定されていないとスルーされて思ったとおりに順番になりませんでした。ですので、そのような場合は下記のような形で配列に含めておく必要がありました。

        \App\Http\Middleware\Hoge::class . ':param1',

指定されているパラメーターが分かっている場合は良いんですが、可変な場合は困りますね。そのような場合はRouter側を拡張してsortMiddlewareメソッド(protected)を書き換えてやる必要がありそうです。