create, store~データの入力と登録
リソースルーティングでは、以下を意図している。
- create
- 登録するデータを作成する。フォーム入力の場合、フォームを持つビューを表示する。
- store
- データをデータベースに登録する。createがフォーム入力の場合、フォームのaction先をこのルートにする。
前提
モデルデータの操作で準備した枠組みを使う。ユーザー認証機能を持ち、ユーザーごとに入力されたシンプルな投稿記事Postを扱う。
流れ
- ドメイン名/posts/createをGETリクエスト
- posts.createルートで- PostsControllerの- createアクションを実行
- createアクションで入力フォームを含むビューを表示
- 入力フォームのactionからposts.storeへルーティング
- posts.storeルートで- PostControllerの- storeアクションを実行
- storeアクションでデータベースにデータを登録
createアクションの呼び出し
リソースルーティングで以下のように設定されていて、ドメイン/posts/createからPostControllerのcreateアクションにルーティングされる。ルーティング名はposts.create。
| 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     | ........ | 
コントローラー~createアクション
コントローラーでは、ビューの$titleを設定してresources/views/posts/create.blade.phpを表示させるだけ。
| 1 2 3 4 5 6 7 8 9 10 11 | class PostController extends Controller {     ........     public function create()     {         return view('posts.create', [             'title' => '新規投稿'         ]);     }     ........ } | 
入力フォームビュー
bladeテンプレート
投稿を入力するフォームはposts/create.blade.phpに以下の要領で記述。
| 1 2 3 4 5 6 7 | <form action="{{ route('posts.store') }}" method="post">   @csrf   <div>     <input type="text" name="comment" placeholder="コメントを入力">   </div>   <input type="submit" value="投稿"> </form> | 
actionで指定しているroute('posts.store')はデータベースへの登録アクションstoreへのルーティング。
| 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     | ........ | 
フォームリクエスト~バリデーション
フォーム入力のバリデーションをフォームリクエストに記述する。
まず、以下のコマンドでフォームリクエストを作成。
| 1 | $ php artisan make:request PostRequest | 
app/Http/Requestsディレクトリーに作成されたPostRequest.phpを編集し、バリデーションルールを追加。ここでは唯一のフォーム入力commentに対して、入力必須(required)と最大200文字(max:200)を配列で設定している。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <?php namespace App\Http\Requests; use Illuminate\Foundation\Http\FormRequest; class PostRequest extends FormRequest {     ........     public function rules()     {         return [             'comment' => ['required', 'max:200'],         ];     } } | 
コントローラー~storeアクション
use指定
PostControllerでPostモデルとPostのフォームリクエストを使うため、以下のようにファイル冒頭でuse指定する(個別の名前空間指定が不要になる)。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Post; use App\Http\Requests\PostRequest; class PostController extends Controller {     ........ } | 
storeアクション
入力フォームのaction先で指定されたアクションメソッドで、フォームの入力をデータベースに書き込む。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | class PostController extends Controller {     ........     public function store(PostRequest $request)     {         Post::create([           'comment' => $request->comment,         ]);         return redirect()->route('posts.index');     }     ........ } | 
ここではPostクラスが継承しているModelクラスのcreate()メソッドで、フォームリクエストのパラメーターをセットしてデータを書き込んでいる。
- 入力バリデーションはマスアサインメント実行時にフォームリクエストで実行され、エラーがあれば$errorsに格納される
- Post::create()は最終的に- Eloquent/Builderの- create()が実行されるらしい(参照:モデルのcreate()メソッドはどこに?)
データ書き込み後posts.indexにリダイレクトしているが、これは投稿記事一覧表示へのルーティング。
モデルでの$fillable設定
create()メソッドによる登録はマスアサインメントになるので、モデルに$fillableを定義しておく。
| 1 2 3 4 5 6 7 8 9 10 | <?php namespace App; use Illuminate\Database\Eloquent\Model; class Post extends Model {     protected $fillable = ['user_id', 'comment', 'image_name']; } | 
確認
ユーザーログイン状態でドメイン名/posts/createをGETリクエストすると入力フォームのページが表示され、投稿ボタンを押すとデータが登録される。
たとえばuser1とuser2をユーザー登録しておいて・・・
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | mysql> SELECT * FROM users\G *************************** 1. row ***************************                id: 1              name: user1             email: user1@mail.com email_verified_at: NULL          password: $2y$10$45lbfGBk84uzZQLi3lahmulUVSQ75xeNSJC42FmS.ayCaW6WyZtfS    remember_token: NULL        created_at: 2021-10-09 10:24:22        updated_at: 2021-10-09 10:24:22 *************************** 2. row ***************************                id: 2              name: user2             email: user2@mail.com email_verified_at: NULL          password: $2y$10$dVAMHnafJLvx4HSyypRfwubvM8ARlAKGa6tqV647xxiBc4i34kixG    remember_token: NULL        created_at: 2021-10-09 10:25:59        updated_at: 2021-10-09 10:25:59 2 rows in set (0.00 sec) | 
それぞれの記事を投稿した結果は以下の通り。
| 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-09 10:34:47 | |  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-09 10:35:32 | |  4 |       2 | user2の2つ目の投稿       | 2021-10-09 10:35:45 | 2021-10-09 10:35:45 | +----+---------+--------------------------+------------+---------------------+---------------------+ 4 rows in set (0.00 sec) |