やりたいこと
表題の通り、where句などで条件で絞ったレコードを指定カラムのみで一括更新したい。
実行環境
Laravel 5.7
注意:他のバージョンでは、別の実装方法で解決ができるかもしれません。
結論
Eloquentを利用せずに、クエリビルダを仕様して更新(update)をする。
クエリビルダではデータベースを直接操作可能になるので、Eloquentを利用するときのEloquentモデル規約などは反映されずに更新したいカラム以外のupdated_at(timestamp型)は更新されなくなる。
DB::table('item')->where('status', 1)->update(['status' => 2]);
検討した実装方法
Eloquentを利用したupdate
特定のカラムの更新のみをしたいときにエレクエントを利用したupdate処理。
itemsテーブルのstatus = 1
をstatus = 2
に更新させたい。
以下のようにするとstatus = 2
に更新はできますが、同時にtimestamps型のupdated_at
も更新されてしまいます。
Item::where('status', 1)->update(['status' => 2]);
ドキュメントにも記載されてます。
デフォルトでEloquentはデータベース上に存在するcreated_at(作成時間)とupdated_at(更新時間)カラムを自動的に更新します。これらのカラムの自動更新をEloquentにしてほしくない場合は、モデルの$timestampsプロパティをfalseに設定してください。
タイムスタンプ
この設定をしてしまうとEloquent全体に適応されてしまうので、今回みたいに一部でのみupdated_at
を利用したくない場合は使えませんでした。
saveメソッドでの更新
saveメソッドも自動でupdate_at
は自動更新されますが、明示的に$item->timestamps = false
とすることで自動更新されなくなります。今回は一括で更新したい。バッチ処理だとクエリ数が多くなるのでこちらも使えませんでした。
$item = Item::where('status', 1)->first();
$item->status = 2;
$item->timestamps = false;
$item->save();
まとめ
普段はEloquentを利用したレコード操作多くて、クエリビルダを全然使ってなかったので解決までに時間がかかりました。。。