鶏口牛後な日々

心の赴くまま、やりたいことを仕事に。

PHP Laravelの登録情報のアップデート画面で、情報が変更された時だけsaveする

ユーザー情報など、つらつらとたくさん保存した内容を、編集画面で編集させるということはよくあると思います。

それを保存する際、新しいuserのインスタンスを作って、いちいちまた入れて、一個ずつまた保存するというのは、ソースも多くなりますし、データベースにも負荷がかかるのではないかと思われます。

これを調べて見たところ、同じような内容で質問している人がStackOverflowにいました。

そもそもsave()が変更したものだけをupdateしてくれるからデータベースの負荷についてのご心配不要

回答を見てスッキリ。内容は日本語にして以下のような感じ。

save()メソッドをつけた時点で、その対応をしているも同然!

このメソッドはそもそも変更になっているかどうかをチェックして、変更になっているもののみデータベースでupdateしてくれるので、全ての項目でいちいちデータベース接続しているわけじゃないんだよ。

とのこと。そうなんだ〜、Laravel作った人、さすが、かしこい!

fill()メソッドを使えば、手間も随分と省ける

さらに別の回答で、 fill() を使えば、手間も省けていいわよ、というものがあり、公式ドキュメントfill() の使い方を調べる。 (公式開いたらトップにスクロールした状態で開くので、当たり前ですが ctrl + ffillable とかfill で検索するとすぐ出ますよ)

この fillable というのは、先にモデルの方で宣言しておくと、updateするときに簡単にソースも少なくスマートにしてくれます。 注意する点としては、bladeの name 属性の名前がリクエスインスタンスの中の項目名にそのままなるため、これをdatabaseのカラム名と一致させておく必要があります。 そうすれば、例えばユーザーのモデル $user について、オートフィルしてもらいたいとすると、コントローラーのメソッドの中で

$user->fill($request->input());
$user->save();

とかくだけで、一致するname属性の変更内容をupdateしてくれるようです。なんて便利!

これをやるには、コントローラーで上記のように書くまえに、先にモデルの方で操作が必要ですので備忘がてらメモしておきます。 (公式見れば早いかもですがw)

まず、アップデートなどで使用したいModelインスタンスを作って、その中で fillable もしくは、guarded を宣言します。

例えば、データベースのテーブルの項目の中で、hogehoge という項目だけ、オートフィルしたい場合は、

protected $fillable = [ 'hoge' ];

と書いておきます。もちろん複数をカンマで繋げて書いてok. これは、いわゆるホワイトリストというもので、逆に、「これとこれ以外は、全部オートフィルしたい」という場合は、 guarded で宣言します。

 protected $guarded = [ 'hoge', 'fuga', 'muhu' ];

これで、hoge, fuga, muhu以外の全てのカラムについて、リクエスト内容から自動で取ってきてfillしてくれ、ということになります。 とっても便利ですね。

一方で、input内容に、一つのテーブルに収まりきらない別の内容が入っていて除外したい場合がありますよね。

そういう時は、コントローラーの方の記述を

$user->fill($request->except('hoge', 'humu'));

としてやればOKです。 except はオブジェクトの配列みたいないわゆる「コレクション」を操作するためのヘルパー関数です。 何かと役に立ちますね。

以上。