はじめに
モデルの新規作成や更新を行う方法がいくつかあるため(さまざまな記事で見かけます)、この際にまとめ、「どれがベストなのか」自分なりの結論を出したいと思います。
検証環境
- macOS Catalina ver 10.15.7
- Docker ver 20.10.5
- docker-compose ver 1.29.0
- Laravel ver 7.30.4
- MySQL ver 8.20.3
$fillableと$guarded
-
「僕がLaravelのEloquentに$fillableでなく$guardedを指定する理由」をまずお読みください。
- こちらに$fillableと$guardedについて書かれています。
- 当然ですが、create()やupdate()、fill()を使用する際に$fillableまたは$guardedのどちらかを定義していないとエラーになります。
$fillableのメリットとデメリット
メリット
- 指定したカラムのみ値の代入を許可する。
デメリット
- カラムが増えるたびにその都度、付け加えなければならない。
- カラム数が多いテーブルは特に大変。
$guardedのメリットとデメリット
メリット
- 値の代入を禁止するカラムだけを指定すれば良いので、カラムが増えても、その都度$guardedに加えなくて良い($guardedとして定義したいカラムが増えれば、都度付け加えなければなりませんが...)。
デメリット
- 指定したカラム以外の値の代入が行われるので、$guardedのみ見た場合、他のどのカラムの操作が許可されているか把握しづらい。
- 言い換えるならば、「$guardedに定義されていないから、あのカラムの代入は許可されている」と逆算しなくてはならないということです。
$fillableまたは$guardedを使う時に注意しなければならないこと
$request->all()を使わない
- 理由は、特定のアクションで意図しない操作が行われる可能性があるからです。以下はその例です。
Post.php
protected $fillable = [
'key1',
'key2',
'key3'
];
PostController.php
public function update(Request $request,Post $post)
{
$data = $request->all();
$post->fill($data)->save();
}
- このupdate()ではkey1とkey2の更新を想定していますが、key3が$dataにある場合、key3の値も更新してしまいます。
- なので$request->only()を使い、意図しない操作を防ぐことを意識しましょう。
モデルの新規作成と更新
新規作成
- $this->カラム = データでのやり方
- 書くのが面倒。
- $fillableまたは$guardedを無視する。
PostController.php
$post = new Post();
$post->store($data); // storeは自分で定義したもの
Post.php
public function store($data)
{
$this->title = $data['title'];
$this->content = $data['content'];
$this->save();
}
- モデル::createでのやり方
- 簡潔で見やすい。
- $fillableまたは$guardedを確認する。
PostController.php
Post::create($data);
更新
- $this->カラム = データでのやり方
- こちらも書くのが面倒。
- $fillableまたは$guardedを無視する。
PostController.php
$post->updateContents($data); //updateContentsは自分で定義したもの
Post.php
public function updateContents($data)
{
$this->title = $data['title'];
$this->title = $data['content'];
$this->save();
}
- update()
- 簡潔で見やすい。
- $fillableまたは$guardedを確認する。
- しかし、「LaravelのORMで初心者から職人へ」にも書いてある通り、直接SQLでデータを入れているため危険であることは認識しなければならない。
PostController.php
$post->update($data);
fill($data)->save()は新規作成と更新のどちらも可能
新規作成
- $post->fill($data)->save()
- インスタンスを作成するのが面倒。
- $fillableまたは$guardedを確認する。
PostController.php
$post = new Post();
$post->fill($data)->save();
更新
- $post->fill($data)->save()
- $fillableまたは$guardedを確認する。
- update()との違いは、「Eloquentのメソッド saveとupdateは処理が異なる」を参照してください。
PostController.php
$post->fill($data)->save();
上記を検討した上で、私が思うモデルの新規作成と更新のベストプラクティス
新規作成
- モデル::create()
更新
- fill($data)->save()
さいごに
いかがだったでしょうか。
まず、$fillableと$guardedについてですが、私は$fillableの方が$guardedより良いのではないかと考えます。なぜなら、繰り返しになりますが、すべてのカラムを把握しなくとも「どのカラムに対して値の代入が許可されているか」見てすぐわかるからです。
次にモデルの新規作成や更新の方法がそれぞれいくつかあることを確認しました。
私と同じく「そのような方法があったんだ!」と新たな発見をし、自身のコードを見直すきっかけになれれば幸いです。
ご指摘およびご意見お待ちしております。
それではまた!
参考サイト
- 「LaravelのORMで初心者から職人へ」
- 「僕がLaravelのEloquentに$fillableでなく$guardedを指定する理由」
- 「Eloquentのメソッド saveとupdateは処理が異なる」