Il est préférable d'utiliser chunkById au lieu de chunk pour éviter de manquer des lignes lors des mises à jour par lots. L'utilisation de chunk peut décaler le décalage des requêtes suivantes après la mise à jour des lignes, entraînant l'omission des lignes non traitées.
Par exemple :
Post::where('processed', 0)->chunk(100, function($posts) { foreach($posts as $post) { $post->processed = 1; $post->save(); } });
Le code ci-dessus génère les requêtes suivantes.
select * from `posts` where `processed` = 0 limit 100 offset 0 select * from `posts` where `processed` = 0 limit 100 offset 100 ...
Le premier morceau met à jour 100 lignes. La deuxième requête, l'ignorant, ignore 100 lignes non traitées car elle utilise toujours le décalage.
Ce qui précède est expliqué en détail par
Thai Nguyen Hung
Lorsque nous essayons de traiter un nombre limité de lignes à l'aide de la méthode chunk() de Laravel, nous pouvons nous attendre à ce que le code suivant ne traite que 5 utilisateurs par lots de 2 :
$query = \App\Models\User::query()->take(5); $query->chunk(2, function ($users) { // Process users });
Cependant, cela traitera tous les utilisateurs de la base de données, deux à la fois. Cela se produit parce que la méthode chunk() de Laravel ignore la limite take() appliquée à la requête, ce qui entraîne le traitement de toutes les lignes en morceaux.
Pour garantir que seul un nombre limité de lignes (par exemple, 5 utilisateurs) sont traitées en morceaux, nous pouvons implémenter un compteur d'index personnalisé qui brisera la boucle de segmentation après avoir atteint la limite spécifiée. Le code suivant y parvient :
class UserProcessor { private int $index = 0; private int $limit = 5; public function process() { $query = \App\Models\User::query(); $query->chunk(2, function ($users) { foreach ($users as $user) { $this->index++; // Process each user here // Example: $user->processData(); if ($this->index >= $this->limit) { // Stop processing after reaching the limit return false; // This will stop chunking } } }); } }
Remarque
Les $index et $limit sont des propriétés de la classe, pas des variables de méthode transmises à la fermeture avec use($index, $limit). En effet, les variables transmises via use() sont copiées dans l'objet de fermeture par valeur. Par conséquent, toute modification à l'intérieur de la fermeture n'affectera pas les valeurs d'origine, c'est pourquoi elles doivent être des propriétés de classe pour être correctement mises à jour et suivre les modifications au fil des itérations.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!