ルーティングとは
LaravelのルーティングはHTTPリクエストのパスや内容に対応するコントローラに処理を渡す役目をします。
公式ドキュメント
ディレクトリ構成
ルーティングファイルは routes
ディレクトリの中にいくつかあります。
ファイル | 説明 |
---|---|
api.php | APIのルーティング |
channels.php | ブロードキャストチャンネルのルーティング |
console.php | コンソールのルーティング |
web.php | 一般のWebページのルーティング |
主に利用するのは web.php
または api.php
になるかと思います。
LaravelをJSONで返すAPIとして利用する場合は api.php
に書いていくことになります。
ビューを表示する
基本
Route::get('/', function () {
return view('welcome');
});
第一引数にルーティングパス、第二引数にコールバックまたはコントローラクラスを渡してルーティングに対応する処理を登録します。
コールバックの中にロジックを書くとルーティングファイルが肥大化するのでコントローラを登録しましょう。
ロジックがなく、シンプルに画面を表示したりリダイレクトのみ行いたい場合はコントローラを登録しなくても良いと思います。
また、view関数で view('welcome')
と指定した場合、 resources/views/welcome.blade.php
を指定したことになります。
補足: PHP7.4以降のコールバックの書き方
PHP7.4からはアロー関数が利用できるのでコールバックをよりシンプルに記述できます。
Route::get('/', fn () => view('welcome'));
ビューを表示するシンプルな書き方
ビューを表示するだけなら view
関数を使うと良いでしょう。
Route::view('/', 'welcome');
文字を返すだけでも表示してくれる
とりあえず文字だけ表示したいって時もシンプルに書けます。
Route::get('health-check', fn () => 'ok');
ルーティングの優先順位について
Laravelのルーティングは上から定義した順に優先されます。
Route::get('articles/{id}', [ArticleController::class, 'show']);
Route::get('articles/create', [ArticleController::class, 'create']);
- '/articles/create' にアクセスした際、ルートパラメータ(
{id}
)にcreate
が渡ってしまい、show
メソッドが呼ばれてしまいます。
Route::get('articles/create', [ArticleController::class, 'create']);
Route::get('articles/{id}', [ArticleController::class, 'show']);
- ルートパラメータ付きの定義は下に書くようにします。
リダイレクトする
単純なリダイレクト処理を行う場合は redirect
関数を使うと良いでしょう。
302
ステータスコードを返します。
Route::redirect('here', 'there');
この例だと /here
にアクセスすると /there
にリダイレクトします。
HTTPリクエストメソッド
HTTPリクエストメソッドに対応するルーティングを登録できます。
Route::get($uri, $callback);
Route::post($uri, $callback);
Route::put($uri, $callback);
Route::patch($uri, $callback);
Route::delete($uri, $callback);
Route::options($uri, $callback);
ルーティングとコントローラの命名
ルートは複数形(articles)
コントローラは単数形または複数形(ArticleController, ArticlesController)
名前付きルートはドット表記(articles.index)
で命名されることが多いです。
リソースコントローラ
Route::resource('articles', ArticleController::class);
resource
関数で登録すると下記のルートを登録したのと同じ内容になります。
Route::get('articles', [ArticleController::class, 'index'])->name('articles.index');
Route::get('articles/create', [ArticleController::class, 'create'])->name('articles.create');
Route::post('articles', [ArticleController::class, 'store'])->name('articles.store');
Route::get('articles/{article}', [ArticleController::class, 'show'])->name('articles.show');
Route::get('articles/{article}/edit', [ArticleController::class, 'edit'])->name('articles.edit');
Route::put('articles/{article}', [ArticleController::class, 'update'])->name('articles.update');
Route::delete('articles/{article}', [ArticleController::class, 'destroy'])->name('articles.destroy');
業務ではシンプルなCRUDではないことも多いのでリソースコントローラは使用せず、個別にルートを定義しています。
補足: リソースコントローラのテンプレートを作成
$ php artisan make:controller ArticleController --resource
--resource
or -r
オプションを付けてコマンドを実行するとリソースコントローラのテンプレートを生成できます。
app/Http/Controllers/ArticleController.php クリックして表示
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ArticleController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
//
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
//
}
}
APIリソースコントローラ
Route::apiResource('articles', ArticleController::class);
create
, edit
を除いたAPI用のルートを登録します。
Route::get('articles', [ArticleController::class, 'index'])->name('articles.index');
Route::post('articles', [ArticleController::class, 'store'])->name('articles.store');
Route::get('articles/{article}', [ArticleController::class, 'show'])->name('articles.show');
Route::put('articles/{article}', [ArticleController::class, 'update'])->name('articles.update');
Route::delete('articles/{article}', [ArticleController::class, 'destroy'])->name('articles.destroy');
補足: APIリソースコントローラのテンプレートを作成
$ php artisan make:controller ArticleController --api
app/Http/Controllers/ArticleController.php クリックして表示
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ArticleController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
//
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
//
}
}
補足: シングルアクションコントローラ
シングルアクションコントローラとは、単一のアクションのみ実行する責務を持つコントローラです。
publicメソッドを1つだけ持たせます。シングルアクションにすることで様々なメリットがあります。
- コードの肥大化が防げる
- 1ファイルの行数が減るため
- 可読性が向上する
- 使用しないプロパティやメソッドを読む必要がないため
- メンテナンス性が向上する
- クラスを分けることでコンフリクトが減る
- 他のアクションの影響を受けないので削除しやすい
Route::get('articles', ArticleIndexControlelr::class)->name('articles.index');
$ php artisan make:controller ArticleIndexControlelr --invokable
--invokable
or -i
オプションを付けてコマンドを実行するとシングルアクションコントローラのテンプレートを生成できます。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ArticleIndexControlelr extends Controller
{
/**
* Handle the incoming request.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function __invoke(Request $request)
{
//
}
}
ルーティングでクラス名のみ渡した時は __invoke
メソッドが実行されます。
https://www.php.net/manual/ja/language.oop5.magic.php#object.invoke
シングルアクションコントローラの場合は __invoke
以外にpublicのメソッドを持ってはいけません。(言語として強制される訳ではありませんが)
__construct
のようなコンストラクタは除いて、シングルアクションコントローラ内でメソッドを分けたい場合はprivateメソッドを定義しましょう。
補足: ルーティングパスの命名規則
- 前後にスラッシュを付けない
- OK:
Route::get('users', ...)
- NG:
Route::get('/users', ...)
- NG:
Route::get('users/', ...)
- OK:
- 名詞を使う、動詞は含めない
- OK:
Route::get('users', ...)
- OK:
Route::delete('users/{id}', ...)
- NG:
Route::get('getUsers', ...)
- NG:
Route::post('users/{id}/delete', ...)
- OK:
- 区切り文字はハイフンを使う
- OK:
Route::get('users/{id}/first-name', ...)
- NG:
Route::get('users/{id}/firstName', ...)
- NG:
Route::get('users/{id}/first_name', ...)
- OK:
- 小文字、特殊記号は避ける
- ファイル拡張子を避ける
- OK:
Route::get('users', ...)
- OK:
Route::get('users.csv', ...)
- OK:
- コマンドではなく、リソースベースで命名する
- OK:
Route::post('users/{id}/activate', ...)
- NG:
Route::post('activate-users/{id}', ...)
- OK:
- Route::resourceを避ける
- 使用するルートを1つ1つ定義する
- ※これは個人の意見
- アンチパターンを避ける
補足: ルーティング系コマンド
ルーティングの一覧を表示するコマンド
$ php artisan route:list
ルーティングをキャッシュするコマンド
$ php artisan route:cache
bootstrap/cache/routes-v7.php
にキャッシュファイルが生成されます。
ちなみにLaravel 6.xまでは bootstrap/cache/routes.php
に生成されていました。
ルーティングのキャッシュをクリアするコマンド
$ php artisan route:clear