Help us understand the problem. What is going on with this article?

Laravelのルーティング優先度でつまづいた話

404エラー発生

以下のルーティング・Controller・Viewを実装したところ/stadium/createにアクセスすることができず、
404エラーが発生しページが存在しないエラーが出ます。(createビューは作成しています。)

web.php
Route::get('/', 'StadiumPostsController@index');
Route::get('/stadium/{id}', 'StadiumPostsController@show');
Route::get('/stadium/{id}/edit', 'StadiumPostsController@edit');
Route::patch('/stadium/{id}', 'StadiumPostsController@update');
Route::post('/stadium', 'StadiumPostsController@store');
Route::get('/stadium/create', 'StadiumPostsController@create');
StadiumPostsController(createメソッドのみ).php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\StadiumPost;

    class StadiumPostsController extends Controller{
         public function create() {
             return view('create');
         }
}
index.blade.php
    <h3>
      <a href="{{ url('/stadium/create') }}">New Stadium</a>
    </h3>

エラー原因

Laravelのルーティング設定では、

上に書かれた設定が優先的に実行される

ということです。

参考
Laravelのルーティングチートシート

なので、web.php/stadium/createが一番下に書かれており、
/stadium/{id}が上にあることで、

  1. idパラメータにcreateという値を受け渡す
  2. Modelからidカラムにcreateという値が存在しない判定になる
  3. idcreateである他のカラムも取得できないため、showメソッドを実行したController側でエラーになる

となってしまいます。

対処方法としては以下の2通りです。

対処方法1:優先度を変更

単純な方法ですが、ルーティングの書く順番を変更すれば対処することができます。
/stadium/{id}を下にして、/stadium/createを上に書くことでエラー回避でき、
ちゃんとController側でcreateメソッドが実行されます。

web.php
Route::get('/', 'StadiumPostsController@index');
Route::get('/stadium/create', 'StadiumPostsController@create'); // 上に移動
Route::get('/stadium/{id}', 'StadiumPostsController@show');// 下に移動
Route::get('/stadium/{id}/edit', 'StadiumPostsController@edit');
Route::patch('/stadium/{id}', 'StadiumPostsController@update');
Route::post('/stadium', 'StadiumPostsController@store');

対処方法2:正規表現で条件分岐

showメソッドを実行するために必要なidパラメータは
正の自然数しか出ないAUTO_INCREMENTになっておりますので、
ルーティングに0-9の数値でしか推移しないよう対処しました。

web.php
Route::get('/', 'StadiumPostsController@index');
Route::get('/stadium/{id}', 'StadiumPostsController@show')->where('id', '[0-9]+'); // 正規表現追加
Route::get('/stadium/{id}/edit', 'StadiumPostsController@edit')->where('id', '[0-9]+');
Route::patch('/stadium/{id}', 'StadiumPostsController@update')->where('id', '[0-9]+');
Route::post('/stadium', 'StadiumPostsController@store');
Route::get('/stadium/create', 'StadiumPostsController@create');
dhiki1234
インフラのエンジニアです。
https://twitter.com/DHIKI_pico
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away