【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');

正規表現についてはこちら。

bonoponz.hatenablog.com

一括で制約

パラメータがひとつだけならルーティングごとに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メソッドを使って制御するのではなく、RouteServiceProviderbootメソッドで一括で制約しましょう。

場所はApp\Providers\RouteServiceProvider.phpです。

public function boot()
{
    Route::pattern('id', '[0-9]+'); // 追記
    parent::boot();
}

これだけです。

web.phpwhereメソッドを使う必要はなくなります。もし使っていたらwhereメソッドを削除しましょう。

これでスッキリですね!

参考URL

ルーティング 7.x Laravel