Laravel Batch Update Multiple Records with SQL Injection Prevention
This article demonstrates how to implement a safe batch‑update method for Laravel's Eloquent models that prevents SQL injection, provides the full PHP implementation, usage example, and the resulting SQL statement, highlighting the performance benefits over individual updates.
Laravel developers know that while the framework offers a convenient way to insert multiple records at once, it does not provide a built‑in method to update many rows in a single query.
Unlike ThinkPHP’s saveAll or CodeIgniter’s update_batch , existing Laravel solutions on StackOverflow often ignore SQL‑injection risks.
This article introduces a custom updateBatch method added to an Eloquent model that builds a prepared UPDATE statement using CASE expressions, thereby protecting against injection.
<code><?php
namespace App\Models;
use DB;
use Illuminate\Database\Eloquent\Model;
/**
* Student model
*/
class Students extends Model
{
protected $table = 'students';
// Batch update
public function updateBatch($multipleData = [])
{
try {
if (empty($multipleData)) {
throw new \Exception("Data cannot be empty");
}
$tableName = DB::getTablePrefix() . $this->getTable(); // table name
$firstRow = current($multipleData);
$updateColumn = array_keys($firstRow);
// Use id as condition by default, otherwise first column
$referenceColumn = isset($firstRow['id']) ? 'id' : current($updateColumn);
unset($updateColumn[0]);
// Build SQL
$updateSql = "UPDATE " . $tableName . " SET ";
$sets = [];
$bindings = [];
foreach ($updateColumn as $uColumn) {
$setSql = "`" . $uColumn . "` = CASE ";
foreach ($multipleData as $data) {
$setSql .= "WHEN `" . $referenceColumn . "` = ? THEN ? ";
$bindings[] = $data[$referenceColumn];
$bindings[] = $data[$uColumn];
}
$setSql .= "ELSE `" . $uColumn . "` END ";
$sets[] = $setSql;
}
$updateSql .= implode(', ', $sets);
$whereIn = collect($multipleData)->pluck($referenceColumn)->values()->all();
$bindings = array_merge($bindings, $whereIn);
$whereIn = rtrim(str_repeat('?,', count($whereIn)), ',');
$updateSql = rtrim($updateSql, ", ") . " WHERE `" . $referenceColumn . "` IN (" . $whereIn . ")";
// Execute prepared statement
return DB::update($updateSql, $bindings);
} catch (\Exception $e) {
return false;
}
}
}
</code>Usage example:
<code>// Data to be batch‑updated
$students = [
['id' => 1, 'name' => '张三', 'email' => '[email protected]'],
['id' => 2, 'name' => '李四', 'email' => '[email protected]'],
];
// Perform batch update
app(Students::class)->updateBatch($students);
</code>The generated SQL looks like this:
<code>UPDATE pre_students
SET NAME = CASE
WHEN id = 1 THEN '张三'
WHEN id = 2 THEN '李四'
ELSE NAME END,
email = CASE
WHEN id = 1 THEN '[email protected]'
WHEN id = 2 THEN '[email protected]'
ELSE email END
WHERE id IN (1, 2)
</code>By updating all rows in a single statement, the method greatly improves efficiency compared with looping individual updates.
php中文网 Courses
php中文网's platform for the latest courses and technical articles, helping PHP learners advance quickly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.