サーバサイドプログラムのリクエスト処理部は、あるURLに対するリクエストを受け取り、リクエストに応じたデータを探して、もしなければ404を返し、と処理を行う必要があります。これを素で書くと例えば次の様になります。
// ルーティングファイル Route::post('user/{id}', 'UserController@update'); // コントローラファイル class UserController { public function update(){ $id = request()->id ?: abort(404); $user = User::findOrFail($id); // $userに関連するレコードを更新する処理 return $user; } }
Laravelのモデル結合ルートはこの処理を簡略化します。使い方は次の通りの名前と型の指定です。
// ルーティングファイル Route::post('user/{user}', 'UserController@update'); // コントローラファイル class UserController { public function update(User $user){ // $userに関連するレコードを更新する処理 return $user; } }
この様にすると、例えばuser/1365とpostを投げた時、User::findOrFail(1365);と同等の動作が実行されupdate関数にはUser::findOrFail(1365);の返り値のUserインスタンスが渡されます。毎度同じ手順で処理を行う必要がなくなり、楽になります。
ルーティング 5.8 Laravel
上記まではモデル結合ルートの基本的な使い方であり、Laravelのデフォルトです。これは主キーで見つけるfindと同等の動作を仕組みを用いていますが、実際には主キーでない何らかのカラムでwhereをかけてモデルを取得したいパターンがあります。そのような時には次の様にモデル内でルートのwhereに使うカラムの名前を指定します。
// vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php /** * @inheritDoc */ public function getRouteKeyName() { return 'モデル結合ルートで使いたいカラム名'; }
このgetRouteKeyName()は次の様にルーティング用のクエリ構築メソッドresolveRouteBindingty中で使われています。このメソッドで返されるModelインスタンスがモデル結合ルートによって渡されるModelのインスタンスになります。
// vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php /** * Retrieve the model for a bound value. * * @param mixed $value * @return \Illuminate\Database\Eloquent\Model|null */ public function resolveRouteBinding($value) { return $this->where($this->getRouteKeyName(), $value)->first(); }
getRouteKeyNameを書き換えることでwhere句の指定するカラム名を書き換えました。もっと深く掘り進めてresolveRouteBindingを書き換えることによって更に大きくモデル結合ルートを改造できます。例えば次です。
public function resolveRouteBinding($value) { return $this->where($this->getRouteKeyName(), $value) ->where('status', '<>', config('const.status.freeze')) ->first(); }
凍結状態のレコードが選ばれた時404を返す様にします。ちょっとしたグローバルスコープのパターンです。
65