Пожалуйста, поправьте меня, если я ошибаюсь, но я думаю, что нет такой вещи, как массовое обновление в модели Eloquent.
Есть ли способ сделать массовое обновление таблицы БД без запроса запроса для каждой строки?
Например, есть ли статический метод, что-то вроде
User::updateWhere( array('age', '<', '18), array( 'under_18' => 1 [, ...] ) );
(да, это глупый пример, но вы получаете картину …)
Почему нет такой функции? Я единственный, кто был бы очень доволен, если что-то вроде этого появится?
Я (разработчики), не хотел бы реализовывать его, как:
DB::table('users')->where('age', '<', 18)->update(array('under_18' => 1));
потому что по мере роста проекта мы можем потребовать от программистов изменить имя таблицы в будущем, и они не смогут выполнить поиск и заменить имя таблицы!
Существует ли такой статический метод для выполнения этой операции? И если этого не произойдет, можем ли мы расширить Illuminate\Database\Eloquent\Model
Class для достижения такой цели?
Для массовых функций обновления / вставки было предложено, но Тейлор Отуэлл (автор Laravel) предлагает, чтобы пользователи вместо этого использовали Query Builder. https://github.com/laravel/framework/issues/1295
Ваши модели должны, как правило, расширять Illuminate \ Database \ Eloquent \ Model. Затем вы получаете доступ к сущности, например, если у вас есть это:
<?php Use Illuminate\Database\Eloquent\Model; class User extends Model { // table name defaults to "users" anyway, so this definition is only for // demonstration on how you can set a custom one protected $table = 'users'; // ... code omited ...
Обновление # 2
Вы должны обратиться к строителю запросов. Чтобы охватить проблему с именами таблиц, вы можете получить ее динамически с помощью метода getTable (). Единственным ограничением этого является то, что вам нужно, чтобы ваш пользовательский класс инициализировался, прежде чем вы сможете использовать эту функцию. Ваш запрос будет выглядеть следующим образом:
$userTable = (new User())->getTable(); DB::table($userTable)->where('age', '<', 18)->update(array('under_18' => 1));
Таким образом, ваше имя таблицы является контроллером в модели User (как показано в примере выше).
Обновление # 1
Другой способ сделать это (неэффективным в вашей ситуации) будет:
$users = User::where('age', '<', 18)->get(); foreach ($users as $user) { $user->field = value; $user->save(); }
Таким образом, имя таблицы хранится в классе пользователей, и ваши разработчики не должны беспокоиться об этом.
Возможно, это было невозможно несколько лет назад, но в последних версиях Laravel вы можете определенно сделать:
User::where('age', '<', 18)->update(['under_18' => 1]);
Стоит отметить, что вам нужен метод where перед вызовом update
.
Используйте транзакции базы данных для обновления нескольких объектов в объеме. Транзакция будет совершена, когда ваша функция обновления завершится или будет отменена, если исключение произойдет где-то посередине.
https://laravel.com/docs/5.4/database#database-transactions
Например, так я восстанавливаю материализованные пули путей ( https://communities.bmc.com/docs/DOC-9902 ) для статей в одном массовом обновлении:
public function regenerateDescendantsSlugs(Model $parent, $old_parent_slug) { $children = $parent->where('full_slug', 'like', "%/$old_parent_slug/%")->get(); \DB::transaction(function () use ($children, $parent, $old_parent_slug) { /** @var Model $child */ foreach ($children as $child) { $new_full_slug = $this->regenerateSlug($parent, $child); $new_full_title = $this->regenerateTitle($parent, $child); \DB::table($parent->getTable()) ->where('full_slug', '=', $child->full_slug) ->update([ 'full_slug' => $new_full_slug, 'full_title' => $new_full_title, ]); } }); }
,public function regenerateDescendantsSlugs(Model $parent, $old_parent_slug) { $children = $parent->where('full_slug', 'like', "%/$old_parent_slug/%")->get(); \DB::transaction(function () use ($children, $parent, $old_parent_slug) { /** @var Model $child */ foreach ($children as $child) { $new_full_slug = $this->regenerateSlug($parent, $child); $new_full_title = $this->regenerateTitle($parent, $child); \DB::table($parent->getTable()) ->where('full_slug', '=', $child->full_slug) ->update([ 'full_slug' => $new_full_slug, 'full_title' => $new_full_title, ]); } }); }