create, store~データの入力と登録
リソースルーティングでは、以下を意図している。
- edit
- データを編集する。フォームで編集する場合、フォームを持つビューを表示する。
- update
- 編集後の内容でデータベースのデータを更新する。editがフォームでの編集の場合、フォームのaction先をこのルートにする。
前提
モデルデータの操作で準備した枠組みを使う。ユーザー認証機能を持ち、ユーザーごとに入力されたシンプルな投稿記事Postを扱う。
流れ
- 編集する記事の$idを指定してドメイン名/posts/(id)/editをGETリクエスト
- posts.editルートで- PostsControllerの- editアクションを実行
- editアクションで編集フォームを含むビューを表示
- 編集フォームのactionからposts.updateへルーティング
 →methodはPATCH
- posts.updateルートで- PostControllerの- updateアクションを実行
- updateアクションでデータベース上のデータを更新
editアクションの呼び出し
リソースルーティングで以下のように設定されていて、ドメイン/posts/(id)/editからPostControllerのeditアクションにルーティングされる。ルーティング名はposts.edit。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | $ php artisan route:list +--------+-----------+------------------------+------------------+------------------------------------------------------------------------+--------------+ | Domain | Method    | URI                    | Name             | Action                                                                 | Middleware   | +--------+-----------+------------------------+------------------+------------------------------------------------------------------------+--------------+ ........ |        | POST      | posts                  | posts.store      | App\Http\Controllers\PostController@store                              | web,auth     | |        | GET|HEAD  | posts                  | posts.index      | App\Http\Controllers\PostController@index                              | web,auth     | |        | GET|HEAD  | posts/create           | posts.create     | App\Http\Controllers\PostController@create                             | web,auth     | |        | GET|HEAD  | posts/{post}           | posts.show       | App\Http\Controllers\PostController@show                               | web,auth     | |        | DELETE    | posts/{post}           | posts.destroy    | App\Http\Controllers\PostController@destroy                            | web,auth     | |        | PUT|PATCH | posts/{post}           | posts.update     | App\Http\Controllers\PostController@update                             | web,auth     | |        | GET|HEAD  | posts/{post}/edit      | posts.edit       | App\Http\Controllers\PostController@edit                               | web,auth     | ........ | 
編集対象の記事を指定してposts.editにGETリクエストでルーティングする例として、以下のようなアンカー要素がある。
| 1 | <a href="{{ route('posts.edit', $post) }}">編集</a> | 
route()メソッドの第2引数でモデルデータを指定すると、自動的にルーティングに沿った形でデータのidがURLに埋め込まれる。
上記の例ではルーティングがposts.editでURLがposts/{post}/editとなっているので、例えば記事idが3の記事の場合は以下のようなURLとなり、これがブラウザーにも表示される。
ドメイン名/posts/3/edit
コントローラー~editアクション
コントローラーでは、ビューの$titleと編集対象の記事のインスタンスを設定してresources/views/posts/edit.blade.phpを表示させる。
editアクションに来る際にURLに埋め込まれたidが、editアクションメソッドの引数$idとして受け取られる。この$idをPostモデルのfind()メソッドの引数に与えて、指定したidの記事データを取得する。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class PostController extends Controller {     ........     public function edit($id)     {       $post = Post::find($id);       return view('posts.edit', [         'title' => '投稿編集',         'post' => $post,       ]);     }     ........ } | 
編集フォームビュー
bladeテンプレート
投稿を編集するフォームはposts/edit.blade.phpに以下の要領で記述。
ここでHTTPのメソッドはPOSTだが、ルーティングではPATCHメソッドを期待しているので、@method('patch')ディレクティブが必要。
| 1 2 3 4 5 6 7 8 |   <form method="post" action="{{ route('posts.update', $post) }}">     @csrf     @method('patch')     <div>       <input type="text" name="comment" value="{{ $post->comment }}">     </div>     <input type="submit" value="更新">   </form> | 
actionで指定しているroute('posts.update', $post)はデータベースの更新アクションupdateへのルーティング。
PATCHに対するルーティングのURLはドメイン名/posts/(id)となる。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | $ php artisan route:list +--------+-----------+------------------------+------------------+------------------------------------------------------------------------+--------------+ | Domain | Method    | URI                    | Name             | Action                                                                 | Middleware   | +--------+-----------+------------------------+------------------+------------------------------------------------------------------------+--------------+ ........ |        | POST      | posts                  | posts.store      | App\Http\Controllers\PostController@store                              | web,auth     | |        | GET|HEAD  | posts                  | posts.index      | App\Http\Controllers\PostController@index                              | web,auth     | |        | GET|HEAD  | posts/create           | posts.create     | App\Http\Controllers\PostController@create                             | web,auth     | |        | GET|HEAD  | posts/{post}           | posts.show       | App\Http\Controllers\PostController@show                               | web,auth     | |        | DELETE    | posts/{post}           | posts.destroy    | App\Http\Controllers\PostController@destroy                            | web,auth     | |        | PUT|PATCH | posts/{post}           | posts.update     | App\Http\Controllers\PostController@update                             | web,auth     | |        | GET|HEAD  | posts/{post}/edit      | posts.edit       | App\Http\Controllers\PostController@edit                               | web,auth     | ........ | 
フォームリクエスト~バリデーション
編集フォームのバリデーションは入力フォームのところで作成したフォームリクエストを使う。
コントローラー~updateアクション
use指定
PostモデルとPostRequestに対するuse指定はフォーム入力で指定済み。
updateアクション
入力フォームのaction先で指定されたアクションメソッドで、編集後の内容でデータベースを更新する。
| 1 2 3 4 5 6 7 8 9 10 11 12 | class PostController extends Controller {     ........     public function update(PostRequest $request, $id)     {         // return 'update:' . $id;         $post = Post::find($id);         $post->update($request->only(['comment']));         return redirect()->route('posts.index');     }     ........ } | 
ここでの要点は以下の通り。
- フォームリクエストのバリデーションを有効にするため、update()メソッドのインジェクションをPostRequestにしている
- update()メソッドの第2引数で、URLに埋め込まれた- idが- $idとして受け取られている
- Postクラスの- find()メソッドの引数に- $idを渡して、指定したidの記事インスタンスを- $postで参照している
- 編集対象記事のインスタンス$postのupdate()メソッドの引数に、更新対象の要素を渡している- 更新対象の要素は、引数のリクエストで得られたフォーム入力のcommentをonly()で限定している
 
- 更新対象の要素は、引数のリクエストで得られたフォーム入力の
- 更新後のデータを含めた一覧表示のため、indexにリダイレクトしている
モデルでの$fillable設定
update()メソッドでのフォームリクエストによる登録はマスアサインメントになるので、モデルに$fillableの定義が必要(フォーム入力のところで定義済み)。
確認
ユーザーログイン状態で<a href="{{ route('posts.edit', $post) }}">編集</a>などでGETリクエストすると編集フォームのページが表示され、更新ボタンを押すとデータが更新される。
| 1 2 3 4 5 6 7 8 9 10 | mysql> SELECT * FROM posts; +----+---------+-----------------------------------+---------------------+---------------------+ | id | user_id | comment                           | created_at          | updated_at          | +----+---------+-----------------------------------+---------------------+---------------------+ |  1 |       1 | user1の1つ目の投稿を編集          | 2021-10-09 10:34:47 | 2021-10-10 11:40:44 | |  2 |       1 | user1の2つ目の投稿                | 2021-10-09 10:35:01 | 2021-10-09 10:35:01 | |  3 |       2 | user2の1つ目の投稿を編集          | 2021-10-09 10:35:32 | 2021-10-10 10:56:10 | |  4 |       2 | user2の2つ目の投稿も編集          | 2021-10-09 10:35:45 | 2021-10-10 10:57:06 | +----+---------+-----------------------------------+---------------------+---------------------+ 4 rows in set (0.00 sec) |