S'il vous plaît, corrigez-moi si je me trompe, mais je pense qu'il n'existe pas de mise à jour massive dans un modèle Eloquent.
Existe-t-il un moyen d'effectuer une mise à jour en masse sur la table de base de données sans émettre de requête pour chaque ligne?
Par exemple, y at-il une méthode statique, quelque chose comme
User::updateWhere(
array('age', '<', '18'),
array(
'under_18' => 1
[, ...]
)
);
(oui, c'est un exemple idiot mais vous obtenez l'image ...)
Pourquoi une telle fonctionnalité n'est-elle pas implémentée? Suis-je le seul qui serait très heureux si quelque chose comme ça se présente?
Je (les développeurs), ne voudrais pas l'implémenter comme:
DB::table('users')->where('age', '<', '18')->update(array('under_18' => 1));
car, au fur et à mesure que le projet se développe, nous pouvons demander aux programmeurs de changer le nom de la table à l'avenir et ils ne peuvent pas rechercher et remplacer le nom de la table!
Existe-t-il une telle méthode statique pour effectuer cette opération? Et s'il n'y en a pas, pouvons-nous étendre la classe Illuminate\Database\Eloquent\Model
pour accomplir une telle chose?
Pour les fonctionnalités de mise à jour/insertion en masse, cela a été demandé, mais Taylor Otwell (auteur de Laravel) suggère aux utilisateurs d’utiliser plutôt le générateur de requêtes. https://github.com/laravel/framework/issues/1295
Vos modèles doivent généralement étendre Illuminate\Database\Eloquent\Model. Ensuite, vous accédez à l'entité iself, par exemple si vous avez ceci:
<?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 ...
Mise à jour # 2
Vous devez avoir recours au constructeur de requêtes. Pour couvrir le problème de nommage des tables, vous pouvez l’obtenir de manière dynamique via la méthode getTable (). La seule limite à cela est que vous devez initialiser votre classe d'utilisateurs avant de pouvoir utiliser cette fonction. Votre requête serait la suivante:
$userTable = (new User())->getTable();
DB::table($userTable)->where('age', '<', 18)->update(array('under_18' => 1));
De cette façon, votre nom de table est controller dans le modèle User (comme illustré dans l'exemple ci-dessus).
Mise à jour n ° 1
Une autre façon de le faire (pas efficace dans votre situation) serait:
$users = User::where('age', '<', 18)->get();
foreach ($users as $user) {
$user->field = value;
$user->save();
}
De cette façon, le nom de la table est conservé dans la classe des utilisateurs et vos développeurs n'ont pas à s'en soucier.
Cela n’était peut-être pas possible il ya quelques années, mais dans les versions récentes de Laravel, vous pouvez certainement le faire:
User::where('age', '<', 18)->update(['under_18' => 1]);
Il est à noter que vous avez besoin de la méthode where avant d'appeler update
.
Utilisez les transactions de base de données pour mettre à jour plusieurs entités en bloc. La transaction sera validée lorsque votre fonction de mise à jour sera terminée ou annulée si une exception survient quelque part entre les deux.
https://laravel.com/docs/5.4/database#database-transactions
Par exemple, voici comment je régénère des slugs de chemin matérialisés ( https://communities.bmc.com/docs/DOC-9902 ) pour des articles dans une seule mise à jour en bloc:
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,
]);
}
});
}
Une petite correction à la réponse de @metamaker:
DB::beginTransaction();
// do all your updates here
foreach ($users as $user) {
$new_value = Rand(1,10) // use your own criteria
DB::table('users')
->where('id', '=', $user->id)
->update([
'status' => $new_value // update your field(s) here
]);
}
// when done commit
DB::commit();
Vous pouvez maintenant avoir 1 million de mises à jour différentes dans une transaction de base de données