Home  >  Article  >  PHP Framework  >  Please do not sort when using chunkById method!

Please do not sort when using chunkById method!

藏色散人
藏色散人forward
2020-11-04 14:25:403752browse

The following tutorial column will introduce you to Laravel. Please do not sort when using the chunkById method! , I hope it will be helpful to friends in need!

Please do not sort when using chunkById method!

Please do not sort when using the chunkById method

I recently encountered a strange problem when doing development tasks. So I share it with you

Problem Description

Since the data needs to be processed in batches, and the amount of this data is very large, it is unrealistic to take it all out at once and then execute it. Fortunately, It is Laravel that provides us with the chunkById method for us to handle conveniently. The pseudo code is as follows

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

At first glance, there is no problem, but when you actually execute the code, you will find that chunkById will only be executed for the first time, and will stop executing for some reason after the second time.

Find the reason

The chunkById code in Laravel’s source code is as follows

  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;
    }

It seems there is no problem, because the while loop is based on $countResults == $count To judge, if we dump these two variables, we will find that the first time they are consistent, the second time the program stops due to inconsistent data.

In the above code, $count is obtained by $results = $clone->forPageAfterId($count, $lastId, $column)->get();,

Continue to view the forPageAfterId method

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);
}

We can see that the results returned here are arranged in ascending order by orderBy, while our original code is arranged in descending order, which will cause the count to be inconsistent, thus ending chunkById implement.

Solution

Just remove the previous orderBy('id', 'desc').

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

Summary

  • Do not add custom sorting when using chunkById or chunk method in the future

  • You can grow old by being cool and learn by learning. . .

The above is the detailed content of Please do not sort when using chunkById method!. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:learnku.com. If there is any infringement, please contact admin@php.cn delete