1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Laravel】ルーティングは優先度に注意して設定する

Last updated at Posted at 2023-09-02

Laravelのルーティングは「上から設定された順番に実行される」という特性がある。
今回は、このルーティングの優先度によって生じるエラーの例と対応策を紹介する。
間違った点があればご指摘いただけますと幸いです。

エラー発生例

Laravelのルーティングは、「上から登録されている順番に実行される」という特性がある。

この特性を知らずにルーティングを設定すると予期しないエラーが発生する恐れがある。
特に、ルートパラメータを使用するときにエラーが起きやすい。

例えば、以下のルーティングファイルで、「/user/create」にアクセスしようとすると、404エラーが発生する。

web.php
Route::get('/user/{id}', [UserController::class, 'show']);
Route::get('/user/create', [UserController::class, 'create']);

エラー要因

ルーティングは上から順番に実行されるため、1つ上の「/user/{id}」を実行しまったのが原因である。
「/user/create」の「create」が「/user/{id}」のルートパラメータidと同じ位置にあるため、createがルートパラメータとして渡されてしまう。
その結果、意図しないコントローラ内のアクションメソッドを実行してしまいエラーに繋がってしまった。

対応策

ルーティングの優先度による上記のようなエラーを避けるための対応策をいくつか紹介する。

順番を変える

ルーティングの順番を変えると簡単にエラーを回避できる。

web.php
Route::get('/user/create', [UserController::class, 'create']);
Route::get('/user/{id}', [UserController::class, 'show']);

しかし、この方法だとルーティングを追加・更新する度に順番を入れ替える必要も出てくるので、あまりおすすめはできない。
そこで、次に紹介するwhereメソッドを使用した正規表現パターンによる制約がおすすめである。

正規表現で制約を付ける

ルートインスタンスのメソッドを使用することで、指定したルートパラメータに正規表現パターンの制約を付けることができる。

whereメソッド (単体で制約したい場合)

ルーティング単体で使用するルートパラメータに制約を付けたい場合はwhereメソッドを使用する。

例えば、ルートパラメータidが数字の時しか実行しないようにしたい場合、以下のようにwhereメソッドで制約を付けることができる

web.php
Route::get('/user/{id}', [UserController::class, 'show'])
    ->where('id', '[0-9]+');
Route::get('/user/create', [UserController::class, 'create']);

patternメソッド (グローバルで制約したい場合)

グローバルでルートパラメータに制約を付けたい場合はpatternメソッドを使用する。

patternメソッドは App\Providers\RouteServiceProviderクラス内のbootメソッドで定義する。

RouteServiceProvider.php
public function boot(): void
{
    Route::pattern('id', '[0-9]+');
}

上記の正規表現パターン定義によって、ルーティングで使用するルートパラメータidは数値のみしか受け付けないという制約が自動的に適用される。

web.php
Route::get('/user/{id}', [UserController::class, 'show'])
// idが数値の場合のみ受け付ける

「id」のように同じ名前のルートパラメータに同じ正規表現パターンの制約を付けたい場合は、whereメソッドを用いて1つ1つ単体で定義するより、patternメソッドを用いてbootメソッド内で一括でパターン定義する方が便利である。


参考サイト
 - Laravel 8.x ルーティング
 - Laravel 404 Not Foundエラーはルーティング順に原因があった

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?