Laravel 自定义 Artisan 命令在完成 50% 时停止

Laravel custom Artisan command stops at 50 percent completion

所以我有一个自定义的 artisan 命令,我编写它来插入一个列并将其存储到一个新列中。我有一个进度条,出于某种原因,当命令完成 50% 时,它会跳到 100%。问题是它只对一半数据执行了代码。

我正在使用 chunk() 函数将数据分成 1,000 行的块,以消除内存耗尽问题。这是必要的,因为我的数据集非常大。

我查看了我的 PHP 错误日志、MySQL 错误日志和 Laravel 日志。我找不到与此命令有关的任何错误或日志行。甚至开始寻找问题的新地方的任何想法。

$jobTitles = ModelName::where($columnName, '<>', '')
            ->whereNull($slugColumnName)
            ->orderBy($columnName)
            ->chunk(1000, function($jobTitles) use($jobCount, $bar, $columnName, $slugColumnName)
        {
            foreach($jobTitles as $jobTitle) 
            {
                $jobTitle->$slugColumnName = Str::slug($jobTitle->$columnName);
                $jobTitle->save();
            }
            $bar->advance(1000);
        });
        $bar->finish();

发生的事情是 whereNull($slugColumnName) 与回调 设置 的结合,$slugColumnName 导致后续循环丢失结果。

事件的顺序是这样的:

  • 获取第一组行:select * from table where column is null limit 100;
  • 对于每一行,将列设置为一个值。
  • 获取下一组行:select * from table where column is null limit 100 offset 100;
  • 继续并增加偏移量,直到不再有结果。

这里的问题是,在第二步之后,您从总数中删除了 100 个结果。假设您从 1000 行开始,到第二个查询时,您现在只有 900 行匹配。

当前 100 行尚未被触及时,这会导致偏移看似 跳过 整个块,从第 100 行开始。

更多官方文档请见this section of this section on chunking

我尚未对此进行测试以验证它是否按您的用例预期工作,但使用 chunkById 似乎可以解决此问题并更正您的结果。