Массовое обновление Laravel для нескольких идентификаторов записей

Я хочу массово обновить свои записи в Laravel, но записи не обновляются. У меня разные записи для каждого идентификатора. Ниже то, что я пытаюсь.

$ids = [5,6,8,9],
$updated_array = [
  ['name' => 'tarun'],
  ['name' => 'Akash'],
  ['name' => 'Soniya'],
  ['name' => 'Shalu'],
];

Model::whereIn('id', $ids)->update($updated_array);

в вашей модели установите protected $guarded = array(); Свойства $fillable и $guarded используются для включения массовой вставки и обновления

lessan 25.07.2018 13:02
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
8
1
10 761
5

Ответы 5

Массовые обновления используются, когда вы пытаетесь обновить несколько строк до одинаковых значений. Вы не можете массово обновлять с разными значениями.

Таким образом, это будет работать, но все соответствующие записи будут обновлены до имени 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.

shailesh yadav 26.07.2018 09:42

Почему нет? Кажется бессмысленным делать это сложнее, чем есть на самом деле, это простой цикл.

Devon 26.07.2018 15:02

если записей 10000, то будет выполнено 10000. Имеет ли смысл выполнять 10000 запросов для простой операции?

shailesh yadav 31.07.2018 07:06

Если это все разные запросы, то да. Вы не обновляете его с теми же значениями ...

Devon 31.07.2018 14:26

Пожалуйста, попробуйте следующий код:

$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 запрос.

shailesh yadav 31.07.2018 07:04

это не пакетный запрос

nima 28.07.2020 14:16

вы можете сделать это так, как указано выше: -

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

Примечание. Я не пробовал и не тестировал ни одно из вышеперечисленных решений.

Другие вопросы по теме