0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Laravelでbulk updateを実装したい場合(DB::statementを用いた例)

Posted at

Laravelで一括の値を更新したい時の処理を簡単にまとめてみました。

use Illuminate\Support\Facades\DB;

public function bulkUpdate(updateRecords)
{
    $updates = [];

    foreach ($updateRecords as $updateRecord) {
        $updates[$updateRecord['id']] = $updateRecord['quantity'];
    }

    $ids = array_keys($updates);

    $sql = "UPDATE update_table SET quantity = CASE id ";

    foreach ($updates as $id => $quantity) {
        $sql .= "WHEN $id THEN $quantity ";
    }

    $sql .= "END WHERE id IN (" . implode(',', $ids) . ")";

    DB::statement($sql);
}

基本的な書き方は上記ですが、この実装にはSQLインジェクションの重大なリスクがあります。

問題点

上記のコードだと、パラメータのバインドを記述していないです。
$id$quantityが直接文字列に挿入されているので、悪意のあるコードが含まれていた場合、SQLインジェクション攻撃が可能になります。

なので、以下のように修正する必要があります。

修正コード

use Illuminate\Support\Facades\DB;

public function bulkUpdate($updateRecords)
{
    $updates = [];

    foreach ($updateRecords as $updateRecord) {
        $updates[$updateRecord['id']] = $updateRecord['quantity'];
    }

    $ids = array_keys($updates);

    $sql = "UPDATE update_table SET quantity = CASE id ";

    $bindings = [];

    foreach ($updates as $id => $quantity) {
        $sql .= "WHEN ? THEN ? ";
        $bindings[] = $id;
        $bindings[] = $quantity;
    }

    $sql .= "END WHERE id IN (" . implode(',', array_fill(0, count($ids), '?')) . ")";

    foreach ($ids as $id) {
        $bindings[] = $id;
    }

    DB::statement($sql, $bindings);
}

変更点

  1. WHEN $id THEN $quantity → WHEN ? THEN ? とし、$bindings$id$quantity を順に追加
  2. WHERE id IN (...) もプレースホルダに置き換え、array_fill? を並べて $bindings$ids を追加

実行されるSQL

UPDATE update_table
SET quantity = CASE id
  WHEN ? THEN ?
  WHEN ? THEN ?
END
WHERE 
  id IN (?, ?)
;

// binding配列は以下の通り
[1, 10, 2, 20, 1, 2]

1つずつupdateのクエリを流す処理を書くのをゼロから調べてコードを書くのが面倒なので、メモとしていつでも引っ張ってこれるように、今回記事にしました。
少しでもお役に立つことができれば嬉しいです。

0
0
0

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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?