Массовое обновление ярко выраженной модели

Пожалуйста, поправьте меня, если я ошибаюсь, но я думаю, что нет такой вещи, как массовое обновление в модели 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, ]); } }); }