Я хочу массово обновить свои записи в Laravel, но записи не обновляются. У меня разные записи для каждого идентификатора. Ниже то, что я пытаюсь.
$ids = [5,6,8,9],
$updated_array = [
['name' => 'tarun'],
['name' => 'Akash'],
['name' => 'Soniya'],
['name' => 'Shalu'],
];
Model::whereIn('id', $ids)->update($updated_array);






Массовые обновления используются, когда вы пытаетесь обновить несколько строк до одинаковых значений. Вы не можете массово обновлять с разными значениями.
Таким образом, это будет работать, но все соответствующие записи будут обновлены до имени tarun:
Model::whereIn('id', $ids)->update(['name' => 'tarun']);
Для вашего примера вы могли бы сделать:
foreach($ids as $key => $id) {
Model::where('id', $id)->update($updated_array[$key]);
}
Но, насколько я знаю, нет способа сделать это, не запустив 4 запроса в Laravel, и написание необработанного оператора SQL для этого было бы даже беспорядочным.
я не хочу запускать цикл foreach.
Почему нет? Кажется бессмысленным делать это сложнее, чем есть на самом деле, это простой цикл.
если записей 10000, то будет выполнено 10000. Имеет ли смысл выполнять 10000 запросов для простой операции?
Если это все разные запросы, то да. Вы не обновляете его с теми же значениями ...
Пожалуйста, попробуйте следующий код:
$data_to_be_updated = [ ['id'=>5,'name' => 'tarun'], ['id'=>6, 'name' => 'Akash'],
['id'=>8, 'name' => 'Soniya'], ['id'=>9,'name' => 'Shalu']
];
foreach ($data_to_be_updated as $key => $value) {
$data = Model::where('id',$value['id'])->first();
if ($data) {
$data->name = $value['name'];
$data->save();
}
}
В приведенном выше примере будет выполнено 8 запросов (4 запроса для выборки записи и 4 для сохранения обновленных данных). Но я хочу выполнить только 1 запрос.
это не пакетный запрос
вы можете сделать это так, как указано выше: -
foreach($ids as $key => $id) {
Model::where('id', $id)->update($updated_array[$key]);
}
Я думаю, что единственный способ сделать это без n запросов - это
Это 3 запроса.
Итерация по n записям для моего приложения также нецелесообразна; Я надеялся, что есть альтернатива, но похоже, что мне придется ее реализовать.
Некоторые хорошие решения этой проблемы можно найти в следующем посте: https://github.com/laravel/ideas/issues/575
1) Можно создать для этого пользовательскую функцию, которая использует необработанный SQL, как указано в комментарии barryvdh в сообщении.
public static function updateValues(array $values)
{
$table = MyModel::getModel()->getTable();
$cases = [];
$ids = [];
$params = [];
foreach ($values as $id => $value) {
$id = (int) $id;
$cases[] = "WHEN {$id} then ?";
$params[] = $value;
$ids[] = $id;
}
$ids = implode(',', $ids);
$cases = implode(' ', $cases);
$params[] = Carbon::now();
return \DB::update("UPDATE `{$table}` SET `value` = CASE `id` {$cases} END, `updated_at` = ? WHERE `id` in ({$ids})", $params);
}
Это, очевидно, увеличивает производительность в 13 раз.
2) Согласно другому комментарию, другая идея состоит в том, чтобы делать это для каждой записи, но делать все это как одну транзакцию, что делает ее намного быстрее.
DB::beginTransaction();
// your loop and updates;
if ( !$user )
{
rollbackTransaction();
} else {
// Else commit the queries
commitTransaction();
}
3) Существует также библиотека laravel, которая пытается решить эту проблему. https://github.com/mavinoo/laravelBatch
Примечание. Я не пробовал и не тестировал ни одно из вышеперечисленных решений.
в вашей модели установите
protected $guarded = array();Свойства$fillableи$guardedиспользуются для включения массовой вставки и обновления