Laravelで、複数のデータをアップデートしたいケースがあると思います。
通常考えられるのは、foreachでインスタンスを1つずつアップデートする方法だと思います。
他にもsave()メソッドやSQLを使う方法などがあるので、それぞれの使い道について、まとめてみます。
update()の使い道
一番一般的な方法だと思います。
App\Flight::where('active', 1)
->update(['delayed' => 1]);
activeカラムが1のレコード全てのdelayedを1にするというコードです。
この方法なら、App\Flight::all()->update(xxx)
とすることで、Flightモデルの全てのレコードに対して、更新をかけることができます。
ただ、ID:1のレコードはdelayedを2にして、ID:2のレコードのdelayedを3にする、というようなレコードによって更新したい値が違う場合は、update()コマンドでは対応できません。
foreach + save()の使い道
$flights = App\Flight::all();
foreach($flights as $flight) {
$flight->name = $request->name;
$flight->save();
}
このように1レコードずつsave()メソッドで保存していく方法です。
これはレコードの数だけクエリが発生するので、かなり重くなると思われます。
save()メソッドを使用する際は、少ない件数か1件のみの時が良いと思います。
foreachで1件ずつ更新するやり方だと、件数によってはメモリリークを起こす可能性がありますので、chunk()
やcursor()
などを使って、分割すると良いと思います。
Laravel(Eloquent): chunk() vs cursor()
保存したい値が変わる場合
上記2つの方法は、1つのモデルに対して、同一データを保存するケースでした。
しかし、FlightモデルのレコードID:1にdelayed:1を保存しつつ、レコードID:2にdelayed:2を保存したい場合もあるかと思います。
この場合は、LaravelのEloquentでは対応できないと思うので、SQL文を作るしかありません。
詳しいやり方については、
超倍速!?複数のレコードの更新を1回で実施するbulk update!
などを参考にしてもらえばと思います。
【おまけ】新規作成ならinsertが使える
アップデートではなく、新規作成したい場合は、create()
、save()
、insert()
を使うことができます。
insert()なら、違う値を1回で保存することができるので、新規データを挿入したい場合はinsert()
メソッドを使うと良いと思います。
ただ、セキュリティが緩くなるようなので、
【Laravel】DBにデータを保存する方法。createとinsertの違いなど
を参考にしながら自己責任で行ってください。
SQLをがっつり書ければ、作成も更新もSQL文で書いた方がいいのかなあと思ってます。