您好,欢迎访问一九零五行业门户网

使用chunkById方法时请不要进行排序!

下面由laravel教程栏目给大家介绍使用chunkbyid方法时请不要进行排序!,希望对需要的朋友有所帮助!
使用 chunkbyid 方法的时候请不要进行排序
最近在做开发任务的时候碰到了个诡异的问题,于是分享给大家
问题说明
由于需要批量处理数据,并且这个数据的量很大,一次全部取出然后执行是不现实的,幸运的是 laravel 为我们提供了 chunkbyid 方法来让我们方便的处理。伪代码如下
student::query() ->where('is_delete', false) ->orderby('id', 'desc') ->chunkbyid(200, function($students) { // 在这里进行逻辑处理 });
咋一眼看上去,并没有什么问题,但是实际执行代码的时候会发现 chunkbyid 只会执行第一次,第二次以后由于某种原因会停止执行。
查找原因
laravel 的源码中 chunkbyid 代码如下
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; }
看起来没什么问题,由于 while 循环是根据 $countresults == $count 来判断的,那么我们 dump 一下这两个变量就会发现, 第一次这两个是一致的,第二次由于数据不一致导致程序停止。
在上面的代码中, $count 是由 $results = $clone->forpageafterid($count, $lastid, $column)->get(); 来获得的,
继续查看 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);}
我们可以看到,在这里返回的结果是 orderby 进行升序排列的, 而我们的原始代码是进行降序排列,就会导致 count 不一致,从而使 chunkbyid 结束执行。
解决方案
把之前的 orderby('id', 'desc') 移除即可。
student::query() ->where('is_delete', false) ->chunkbyid(200, function($students) { // 在这里进行逻辑处理 });
总结
以后使用 chunkbyid 或者 chunk 方法的时候不要添加自定义的排序
骚到老,学到老。。。
以上就是使用chunkbyid方法时请不要进行排序!的详细内容。
其它类似信息

推荐信息