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) |