株式会社クイックのWebサービス開発blog

HAPPYなサービスプランナー・エンジニア・デザイナーのブログです。

【Laravel】Middlewareでルートパラメータチェックする時のテクニック

こんにちは、最近ロードバイクにはまっているぱふゅーむです。
現在チームでは、ロードバイクがブームでこの半年で4人が購入しています。
ただの置物にしちゃっているメンバーが1名いますが笑(たまに座って満足しているそうです、怖いですね。。)

ということで今回はロードバイクのすすめ・・・ではなく LaravelのMiddlewareを使ったちょっとしたテクニックを紹介したいと思います。

Middlewareについて

Middlewareの詳細な説明は今回は割愛します。
詳細を確認したい方はこちらをご覧ください。=> Laravel - ウェブ職人のためのPHPフレームワーク Middleware

ルートパラメータチェックをMiddlewareで行い、ついでに取得した値をリクエストに内包する

ルートパラメータで取得したidが存在するかMiddlewareでチェックしたいケースなどに使えるテクニックです。
Middleware内でfind()したモデルをリクエストに内包することで、 Controllerに渡した後、再度取得する処理を省略することができます。

以下のようなルーティングを設定していたとします。

Route::get('/{hogeId}', 'HogeController@detail')->middleware('ValidatePkMiddleware')
Route::get('/{fugaId}', 'FugaController@detail')->middleware('ValidatePkMiddleware')

Middleware内でidの存在をチェックしたいModelを、配列で定義します。

<php

class ValidatePkMiddleware
{
    /**
     * routeで指定したidの存在を確認し、検索結果をrequestに含める(Controllerで使用可能にする)
     * Controller での参照は xxxId の場合は 「$request->xxx」(Idを取り除いた形式) となる
     * ※ 存在確認が主目的なので、結合などは考慮しない
     *
     * @var array [ routeで指定したKey => 対象Model ]
     */
    private static $validateList = [
        'hogeId' => Hoge::class,
        'fugaId' => Fuga::class,
    ];


上記で定義した配列を使用し、以下のようにルートパラメーターを取得、存在をチェックします。
この例では存在しなかった場合404を投げるようにしています。

存在チェックにexists()を使用せず、find()しているところがミソです。
存在した場合、リクエストに内包し、Controller以下の処理で値を参照できるようにしています。
このようにすることで、各処理でfind()を省略することができます。

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        foreach (self::$validateList as $routeKey => $modelClass) {
            $key = $request->route($routeKey);
            if ($key === null) {
                continue;
            }
            $model = (new $modelClass())->find((int) $key);
            if ($model === null) {
                abort(404, trans('messages.not_found'));
            }
            $requestKey = str_replace('Id', '', $routeKey);
            $request->merge([
                'fromDb' => (object) [$requestKey => $model],
            ]);
        }

        return $next($request);
    }
}

単純ですが、こういったちょっとした工夫の積み重ねで、後の実装が楽になりますよね!


\\『明日のはたらくを創る』仲間を募集中です!! //
919.jp