LoginSignup
15
19

More than 3 years have passed since last update.

【Laravel】バルクアップデートを行う方法

Last updated at Posted at 2019-08-05

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文で書いた方がいいのかなあと思ってます。

15
19
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
19