どーも!
たかぽんです!
今回はLaravelのルーティングをする際にいい感じにまとめる方法を調べていきます...!
ルーティングをまとめる方法!
今回はLaravelでルーティングを設定することがあると思います。
その際にどんな方法でまとめればいいのか?
この際に今一度確認をして、一通りまとめておこうと思います!
ルーティングをまとめるとは・・・
さて、まずはルーティングをまとめる...?というのはどういうことか説明をしておきます。
Laravelでのルーティングは、Webサービスの場合に、ユーザーがブラウザからアクセスをする際、"http://localhost/test"
というパスにアクセスをした場合に、Laavelで作成した"welcome"viewを表示する...!
といった、アクセス時のURLと表示するviewや処理の対応を設定するのがルーティングになります。
上記を簡単にコードにすると...
Route::get('/test', function () {
return view('welcome');
});
こんな感じです。
Laravelではデフォルトだと、"routes/web.php"に記載することになっています。
詳しい説明は割愛しますね。
そういったルーティングを設定する場合、例えば"http://localhost/test/hoge"
といったURL、"http://localhost/test/huga"
といったURLがあったとします。
このルーティングを作る場合...
Route::get('/test/hoge', function () {
return view('welcome');
});
Route::get('/test/huga', function () {
return view('welcome');
});
このような感じになります。(本来は返すviewを変えたりしますが、今回はそこは割愛します...!)
この場合、都度都度getで別のルートを定義していく...といったこともできますが、ルートに共通部分(今回は"test")があれば、それをまとめてしまいたい...!
というのが今回のやりたいことになります...!
まとめる前の状態
まず、ルーティングをまとめる前の状況を置いておきます。
// viewを直接返す場合の例
Route::get('/test/takapon/hoge', function () {
return view('takapon');
});
Route::get('/test/takapon/huga', function () {
return view('takapon');
});
Route::get('/test/laravel', function () {
return view('laravel');
});
// Controllerを呼び出す場合の例 (laravel8.xの記述)
Route::get('/test/takapon/hoge',[TakaponController::class, 'index']);
Route::get('/test/takapon/huga',[TakaponController::class, 'index']);
Route::get('/test/laravel',[TakaponController::class, 'index']);
簡単に説明しておくと、viewをそのまま返すルーティングと、Controllerのアクションを呼び出すような書き方ですね。
それぞれ3つのルーティングがあり、そのうち、"test"は全てに共通、"test/takapon"は一部で共通している...といった状況です。
Controller, view側の処理は割愛します...!(今回はテストのため、routingに限らず同じview, actionにしちゃってます...w)
では、それぞれの場合でどんなふうになるのか?を書いていきます。
prefixを用いてまとめる方法
まずはprefix(先頭部分)でまとめる方法です。
prefixメソッドを使うことで、前方で一致している部分があればまとめることが可能です。
// viewを直接返す場合の例
Route::prefix('test')->group(function () {
Route::prefix('takapon')->group(function () {
Route::get('hoge', function () {
return view('welcome');
});
Route::get('huga', function () {
return view('welcome');
});
});
Route::get('laravel', function () {
return view('welcome');
});
});
// 繋げての書き方も可能(ただし、"test/laravel"のルートは別途定義が必要になる)
Route::prefix('test/takapon')->group(function () {
Route::get('hoge', function () {
return view('welcome');
});
Route::get('huga', function () {
return view('welcome');
});
});
// Controllerを呼び出す場合の例
Route::prefix('test')->group(function () {
Route::prefix('takapon')->group(function () {
Route::get('hoge',[TakaponController::class, 'index']);
Route::get('huga',[TakaponController::class, 'index']);
});
Route::get('laravel',[TakaponController::class, 'index']);
});
// 繋げての書き方も可能(ただし、"test/laravel"のルートは別途定義が必要になる)
Route::prefix('test/takapon')->group(function () {
Route::get('hoge',[TakaponController::class, 'index']);
Route::get('huga',[TakaponController::class, 'index']);
});
さて、簡単に補足しておくと、prefixというのは異パン的に先頭部分を意味します。
今回はURIのprefix...という意味合いになるため、例えば....
"http://localhost/test/hoge"
という文字があった場合、"http://localhost"
まではアプリの設定できめるので、除外し、その後の"/test/hoge"がprefixになり得ます。
なり得ます...というのは、"/test"をprefixと見ることも可能ですし、"/test/hoge"をprefixと見ることも可能...という意味合いを含んでます。(先頭からある一定範囲までのことをprefixと呼ぶことがあります)
そのため、先頭から"test"の分をprefixと見た場合...
以下のようにすれば設定が可能です。(指定時に、最初の"/"は省略可能です)
Route::prefix('test')->group(function () {
// 後続のルート情報を記載
}
さらに細かく、"/test/hoge"をprefixとした場合、以下のようにも設定が可能です。
Route::prefix('test/hoge')->group(function () {
// 後続のルート情報を記載
}
ただし...!
prefixとして、"test/hoge"で括った場合、仮に、test部分のみ共通する、他の"test/huga"等があったとしたら、別で括ってあげる必要が有ります。
そのため、prefixの場合は、prefixで最初に"test"を括り、その中で再度"hoge"等で括ってあげる形がおすすめです。
(特定のURIを直接指定するか、手前から順々に指定していくか...といった違いですね...!)
今後、途中のURIから派生することが無いと言い切れるのであれば、直接指定しても良いと思いますが...、大抵は細かく指定してく方が良くなるかと思います...!
最後に、Laravelの公式資料の翻訳ページを添付しておきます。
是非一読してみてください..!
ルートのnameも括る場合
さて、ルートの括り方はわかったので、次はnameも括ってみます。
ルートに名前をつけることができるのですが、その場合にどうすればいいのか?についてみていきたいと思います。
Route::prefix('test')->name('test.')->group(function () {
Route::prefix('takapon')->name('takapon.')->group(function () {
Route::get('hoge', function () {
return view('welcome');
})->name('hoge');
Route::get('huga', function () {
return view('welcome');
})->name('huga');
});
Route::get('laravel', function () {
return view('welcome');
})->name('laravel');
});
まずはview呼び出しを直接行なってるパターンでみていきます。
ご覧いただくとわかりますが、nameメソッドで、名前の先頭には"test."っていう名前をつけるよ!
といった指定をしています。
こうすることによって、そのgroup内で書かれているルートには全てその効果が適応されるわけですね...!
一応、"php artisan route:list"コマンドで確認をしておきます。
ちゃんと、
+--------+----------+-------------------+-------------------+---------+------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+----------+-------------------+-------------------+---------+------------+
| | GET|HEAD | test/laravel | test.laravel | Closure | web |
| | GET|HEAD | test/takapon/hoge | test.takapon.hoge | Closure | web |
| | GET|HEAD | test/takapon/huga | test.takapon.huga | Closure | web |
+--------+----------+-------------------+-------------------+---------+------------+
URIとNameがちゃんと対応していますね...!
理想はURIとNameは一致させることがベストになるかなと思います。
そのため、nameをつける場合は、同じくnameも括ってあげた方が管理がしやすいかと思います。
では、次に、コントローラを呼び出しているパターンもみておきます。(といっても、対して変わりませんが...!)
Route::prefix('test')->name('test.')->group(function () {
Route::prefix('takapon')->name('takapon.')->group(function () {
Route::get('hoge',[TakaponController::class, 'index'])->name('hoge');
Route::get('huga',[TakaponController::class, 'index'])->name('huga');
});
Route::get('laravel',[TakaponController::class, 'index'])->name('laravel');
});
同じくnameメソッドで括ってあげればいい感じですね...!
確認しておくと、ちゃんとNameもついています。
+--------+----------+-------------------+-------------------+----------------------------------------------+------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+----------+-------------------+-------------------+----------------------------------------------+------------+
| | GET|HEAD | test/laravel | test.laravel | App\Http\Controllers\TakaponController@index | web |
| | GET|HEAD | test/takapon/hoge | test.takapon.hoge | App\Http\Controllers\TakaponController@index | web |
| | GET|HEAD | test/takapon/huga | test.takapon.huga | App\Http\Controllers\TakaponController@index | web |
+--------+----------+-------------------+-------------------+----------------------------------------------+------------+
また、こちらも複数繋げての指定も可能です。
例えば以下のような感じです。
Route::prefix('test/takapon')->name('test.takapon.')->group(function () {
Route::get('hoge',[TakaponController::class, 'index'])->name('hoge');
Route::get('huga',[TakaponController::class, 'index'])->name('huga');
});
こう指定すると...
+--------+----------+-------------------+-------------------+----------------------------------------------+------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+----------+-------------------+-------------------+----------------------------------------------+------------+
| | GET|HEAD | test/takapon/hoge | test.takapon.hoge | App\Http\Controllers\TakaponController@index | web |
| | GET|HEAD | test/takapon/huga | test.takapon.huga | App\Http\Controllers\TakaponController@index | web |
+--------+----------+-------------------+-------------------+----------------------------------------------+------------+
ちゃんと繋がってくれるんですね...!
他のまとめる方法
さて、他にもまとめる方法として、Resourcesメソッド...というものがあります。
ただし、この手法は少し癖があるため、それをある程度理解した上で使用する必要があります。
簡単に説明しておくと、RESTful APIという、RESTの原則(システム同志の連携の際に用いる考え方の一つ)に則った形でのAPI設計があり、その構築をする場合にとても便利な機能がこのResourcesメソッドです。
LaravelではEloquentのモデルをリソースとして考えた場合、そのリソースに対するアクションをこのResourcesメソッドで一括で作成できます。
例えば...
公式でも説明されていますが、Photoモデル...といったモデルがあったとします。
すると、そのモデルをリソースと考えると、作成や読み取り、更新削除...といった、基本的なアクションが必要になります。
そういったものはあらかじめまとめて作っちゃおうぜ!というのがResourcesのやれることなんですね。
実際に、一つルーティングを書いてあげれば最大7つ分ほどのルーティングを書いたことになりますし、それぞれのURIやnameも自動で作成されます。
ただ、既存のルーティングをまとめる...という用途とは少し違うので、今回はこの程度にしておきます。
使用する場合は、公式ページを参照してみてください。
余談
最後に、前述したRESTfulなルート指定ですが、以前は以下のようにも指定できました。
Route::controller('users', 'UserController');
上記をルーティングに指定した上で、"UserController"にて、以下のように指定すればいい感じにgetやpostで判別してくれてたんですね。
class UserController extends BaseController {
public function getIndex()
{
//
}
public function postProfile()
{
//
}
public function anyLogin()
{
//
}
}
しかしながら、上記の"Route::controller"は5.3の時点で廃止されているため、もう使えません。
調べていると、ちょこちょこ見かけたので、念の為記載しておきます。
上記の非推奨の項目として...
Route::controller
を使う暗黙のコントローラルート定義は非推奨になりました。ルートファイルで明確に定義してください。これはパッケージから削除されます。
とありますね。
まぁ、Controller以下が暗黙で定義されているとわかりづらい...等あるからでしょうね。
もしRoute::controllerは使えない...ことは気をつけていきましょう!(ただし、古い場合は使ってるものもあるかもしれないです。その場合はとりあえずバージョン上げるようにがんばりましょう...)
まとめ
さて、今回はルーティングをまとめる方法を見ていきました...!
いくつか方法があったりするのかな?
と思いましたが、現状はprefixとnameで括っていく形が最もベストな気がします。
公式の資料を眺めていると、アクセス回数の制限等もかけられることをしって、まだまだ使ったことない機能案外多いな...と改めて感じました...w
それでわ!