今回は Route Model Binding 機能を使って、コントローラを修正したいと思います。Route Model Binding とは、今までモデルの id を受け取っていた箇所で、id の代わりに、id に対応するモデルのインスタンスを受け取れる便利な機能です。
ルートの確認
php artisan route:list +--------+-----------+-------------------------+------------------+------------------------------------------------------------------------+--------------+ | Domain | Method | URI | Name | Action | Middleware | | | DELETE | articles/{article} | articles.destroy | App\Http\Controllers\ArticlesController@destroy | web,auth | | | PUT|PATCH | articles/{article} | articles.update | App\Http\Controllers\ArticlesController@update | web,auth | | | GET|HEAD | articles/{article} | articles.show | App\Http\Controllers\ArticlesController@show | web | | | GET|HEAD | articles/{article}/edit | articles.edit | App\Http\Controllers\ArticlesController@edit | web,auth | +--------+-----------+-------------------------+------------------+------------------------------------------------------------------------+--------------+
{article} パラメータを受け取っているアクションが4つあります。
- articles.show
- articles.edit
- articles.update
- articles.destroy
これらのルートのコントローラメソッドでは、id で Articleを検索する処理が実行されています。
$article = Article::findOrFail($id);
// app/Http/Controllers/ArticlesController.php ... class ArticlesController extends Controller { ... public function show($id) { $article = Article::findOrFail($id); // $id で Articleを検索 return view('articles.show', compact('article')); } ... public function edit($id) { $article = Article::findOrFail($id); // $id で Articleを検索 return view('articles.edit', compact('article')); } public function update(ArticleRequest $request, $id) { $article = Article::findOrFail($id); // $id で Articleを検索 $article->update($request->validated()); return redirect()->route('articles.show', [$article->id]) ->with('message', '記事を更新しました。'); } public function destroy($id) { $article = Article::findOrFail($id); // $id で Articleを検索 $article->delete(); return redirect()->route('articles.index') ->with('message', '記事を削除しました。'); } }
Route Model Binding を使うと、この検索処理をコントローラで実行する必要がなくなります。
Route Model Binding
ArticlesController.php を修正します。
// app/Http/Controllers/ArticlesController.php ... class ArticlesController extends Controller { ... public function show(Article $article) { // $id から $article へ変更 return view('articles.show', compact('article')); } ... public function edit(Article $article) { // $id から $article へ変更 return view('articles.edit', compact('article')); } public function update(ArticleRequest $request, Article $article) { // $id から $article へ変更 $article->update($request->validated()); return redirect()->route('articles.show', [$article->id]) ->with('message', '記事を更新しました。'); } public function destroy(Article $article) { // $id から $article へ変更 $article->delete(); return redirect()->route('articles.index') ->with('message', '記事を削除しました。'); } }
今まで、$id を引数に受け取っていた4つのメソッドを Article $article を受け取るように変更しました。
Article::findOrFail($id); で、$id から記事を検索していた処理は削除しました。
驚いた事に、これだけで自動的にルートの {article} 部分に指定された id に一致する Article が $article 変数に渡されてきます。この機能を Route Model Bindeing といいます。
ルートの {article} パラメータとコントローラの $article 引数は名前を合わせておく必要があります。
今までのコントローラでも十分にシンプルだと思っていましたが、更にシンプルになり、超クールです。
公式サイト
http://laravel.com/docs/5.6/routing#route-model-binding