Laravel(7以下)でBulkUpsert

Bulk Upsertとは

LaravelでBulk InsertやBulk UpdateならぬUpsert(既にあればUpdate,無ければInsert)も
バルクでやりたいという場面があった。
以下のBulk Insertのようなシンプルなコードからはほど遠くなったので言い訳をしたい。
(Bulk Insertの例)

$faker = Faker::create();
$params = [];
for ($i=0; $i < 10000; $i++) { 
  $params[] = [ 
     'name' => $faker->name(),
     'password' => $faker->password(),
  ];
}
User::insert($params);

Laravel8以上ではなかった。

Laravel8以上で開発をしている方、良かったですね。
Laravel8からはEloquent::upsertというメソッドが実装されたようです。
Laravel8の方は以上でreturnとなります。
Laravel 8.x Eloquentの準備

データを一様に変更する訳ではなかった。

Bulk UpsertやBulk Updateと言っても、ステータス的なカラムを一様に変更するか
それぞれ違うデータに変更するかで異なります。データを一様に変更するのは比較的簡単です。
Eloquentで絞り込めんでそのまま変えてしまえる場合は以下で済む。
これはそもそもBulkUpdateとわざわざ言うのか、よく分かりません。

User::where("name", "LIKE", "%Bob%")->update(['weight' => 'fat']);

また、フロントから配列を受け取る場合でもwherein句で済む。

$ids = $request['ids'];
User::wherein("id", $ids)->update(['age' => 'youth']);

updateOrCreateは複数データにどう使うか分からなかった。

updateOrCreateメソッドという変な名前のメソッドがあり、upsertとはきっとこれだと思ったが、
以下のように書いて、例えばA型のデータであれば性格は正直者となるとのこと。
A型の人がいなければUser自体を作るとのこと。

User::updateOrCreate(['blood_type' => 'A'], ['personality' => 'honest']);

複数の場合は更に[]で囲うんですかね、調べてもよく分からなかったので諦めました。
このメソッドをどのように複数に使うのか、もし知っていたら教えて欲しいです。
Laravel 5.7 Eloquent:利用の開始

データをそれぞれ変える場合はSQLを書くしかなかった。

結局はSQLでできることなのだから、DB::statementメソッドを使えば何とかなる通り。
SQLのInsert...ON DUPLICATE KEY)を作った配列でぶちこむことで凌げた。
Eloquentにできないこともsqlにはできる、生のsqlこそ至高!とはなりませんが、めでたしめでたし。
INSERT ... ON DUPLICATE KEY UPDATE 構文

foreach ($users as $user) {
  //文字連結で見づらいが(user_id, user_name, user_status)を作りたいだけ。
  $bulk_sql = $bulk.'('.$user->id.','.'$user->name,'.$user->status),';
}
//最後の行のカンマを抜く
$bulk_data = substr($bulk, 0, -1);
$sql_upsert = <<<SQL
                INSERT INTO users (id, name, status) 
                VALUES
                .$bulk_data.
                ON DUPLICATE KEY
                UPDATE 
                    id = VALUES(id),
                    name = VALUES(name),
                    status = VALUES(status)
            SQL;
// SQLの実行
DB::statement($sql_upsert);
おすすめの記事