【Laravel】ルーティングにおける変数の値を制限する
もくじ
ルーティングにおける変数の型
Route::get('/sample/{id}', 'IndexController@sample');
仮に上記のようなルーティングがあったとします。
ここで何も指定しない場合、{id}
の値は何でもOK状態です。
/sample/1 /sample/004 /sample/あああ /sample/3q948yqp39v4
型は常に文字列
/sample/12
にアクセスした場合id=12
と思いきやid='12'
となっており、一見integerのようですが型を確認すると実はstring扱いになってしまいます。
そのため、コントローラーなどでこの{id}
を数字で使いたい時に思うような動きにならないこともあります。(実際私が陥りました。)
正規表現制約
ルーティングで扱う変数の制約をします。
Route::get('/sample/{id}', 'IndexController@sample')->where('id', '[0-9]+');
うしろにwhere
メソッドを追加するだけでOKです。
複数のパラメータ名があっても問題ありません。
Route::get('/sample/{id}/{name}', 'IndexController@sample')->where(['id' => '[0-9]+', 'name' => '[a-z]+']);
nameメソッドと共にも使えます。付け足すだけです。
Route::get('/sample/{id}', 'IndexController@sample')->where('id', '[0-9]+')->name('sample');
正規表現についてはこちら。
一括で制約
パラメータがひとつだけならルーティングごとにwhereメソッドを使うだけでいいですが、何度も同じパラメータ名を使用する場合は一括で制約することができます。
Route::get('/sample/{id}', 'IndexController@sample'); Route::get('/sample/{id}/list', 'IndexController@list'); Route::get('/sample/{id}/stock', 'IndexController@stock'); Route::get('/sample/{id}/shop', 'IndexController@shop');
上記のように複数箇所で{id}
を使うルーティングがあると正直面倒くさい上に保守性も低くなります。
Route::get('/sample/{id}', 'IndexController@sample')->where('id', '[0-9]+'); Route::get('/sample/{id}/list', 'IndexController@list')->where('id', '[0-9]+'); Route::get('/sample/{id}/stock', 'IndexController@stock')->where('id', '[0-9]+'); Route::get('/sample/{id}/shop', 'IndexController@shop')->where('id', '[0-9]+');
問題はないけれど綺麗でもありませんよね。
グローバル制約
ひとつひとつwhere
メソッドを使って制御するのではなく、RouteServiceProvider
のboot
メソッドで一括で制約しましょう。
場所はApp\Providers\RouteServiceProvider.php
です。
public function boot() { Route::pattern('id', '[0-9]+'); // 追記 parent::boot(); }
これだけです。
web.php
でwhere
メソッドを使う必要はなくなります。もし使っていたらwhere
メソッドを削除しましょう。
これでスッキリですね!