Maison  >  Article  >  cadre php  >  Veuillez ne pas trier lorsque vous utilisez la méthode chunkById !

Veuillez ne pas trier lorsque vous utilisez la méthode chunkById !

藏色散人
藏色散人avant
2020-11-04 14:25:403813parcourir

La colonne du didacticiel suivante de Laravel vous présentera. Veuillez ne pas trier lorsque vous utilisez la méthode chunkById ! , j'espère que cela sera utile aux amis dans le besoin !

Veuillez ne pas trier lorsque vous utilisez la méthode chunkById !

Veuillez ne pas trier lorsque vous utilisez la méthode chunkById

J'ai récemment rencontré un problème étrange lors de l'exécution de tâches de développement. Je partage donc. avec tout le monde

Description du problème

En raison de la nécessité d'un traitement par lots des données et de la quantité de ces données est très importante, il est irréaliste de tout prendre dehors immédiatement, puis exécutez-le. Heureusement, c'est Laravel qui nous fournit la méthode chunkById que nous pouvons gérer facilement. Le pseudocode est le suivant

Student::query()
    ->where('is_delete', false)
    ->orderBy('id', 'DESC')
    ->chunkById(200, function($students) {
            // 在这里进行逻辑处理
    });

À première vue, il n'y a pas de problème, mais lorsque vous exécutez réellement le code, vous constaterez que chunkById ne sera exécuté que pour la première fois et cessera de s'exécuter pour une raison quelconque après la deuxième fois.

Trouvez la raison

Le code chunkById dans le code source de Laravel est le suivant

  public function chunkById($count, callable $callback, $column = null, $alias = null)
    {
        $column = is_null($column) ? $this->getModel()->getKeyName() : $column;
        $alias = is_null($alias) ? $column : $alias;
        $lastId = null;
        do {
            $clone = clone $this;
            $results = $clone->forPageAfterId($count, $lastId, $column)->get();
            $countResults = $results->count();
            if ($countResults == 0) {
                break;
            }
            if ($callback($results) === false) {
                return false;
            }
            $lastId = $results->last()->{$alias};
            unset($results);
        } while ($countResults == $count);
        return true;
    }

Il semble qu'il n'y ait pas de problème, car la boucle while est basé sur $countResults == $count Pour en juger, si nous dumpons ces deux variables, nous constaterons que la première fois elles sont cohérentes, la deuxième fois le programme s'arrête en raison de données incohérentes.

Dans le code ci-dessus, $count est obtenu par $results = $clone->forPageAfterId($count, $lastId, $column)->get();,

Continuer pour regarder la méthode forPageAfterId

public function forPageAfterId($perPage = 15, $lastId = 0, $column = 'id')
{
    $this->orders = $this->removeExistingOrdersFor($column);
    if (! is_null($lastId)) {
        $this->where($column, '>', $lastId);
    }
    return $this->orderBy($column, 'asc')
                ->take($perPage);
}

Nous pouvons voir que les résultats renvoyés ici sont classés par ordre croissant par orderBy, tandis que notre code d'origine est classé par ordre décroissant, ce qui rendra le décompte incohérent, mettant ainsi fin chunkById implémente.

Solution

Supprimez simplement le orderBy('id', 'desc') précédent.

Student::query()
    ->where('is_delete', false)
    ->chunkById(200, function($students) {
            // 在这里进行逻辑处理
    });

Résumé

  • N'ajoutez pas de tri personnalisé lors de l'utilisation de chunkById ou de la méthode chunk à l'avenir

  • Soyez cool et apprenez jusqu'à ce que vous vieillissiez. . .

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!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer