Laravel Artisan 命令底层集成了 Symfony Console 组件,可轻松实现控制台可视化进度条。
一、基础用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| <?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class BatchProcess extends Command { protected $signature = 'batch:process'; protected $description = '批量处理数据';
public function handle() { $userIds = range(1, 1000); $total = count($userIds);
$bar = $this->output->createProgressBar($total); $bar->start();
foreach ($userIds as $id) { usleep(10000); $bar->advance(); }
$bar->finish();
$this->newLine(); $this->info('处理完成!'); } }
|
二、核心方法说明
| 方法 |
作用 |
createProgressBar($max) |
创建进度条对象,$max 为总步数 |
start() |
输出初始进度条 |
advance($step = 1) |
前进指定步数(默认 1) |
finish() |
强制完成进度条,输出 100% |
三、自定义格式
1
| $bar->setFormat(" %current%/%max% [%bar%] %percent:3s%% %elapsed:6s% / %estimated:-6s% %memory:6s%");
|
常用占位符:
| 占位符 |
含义 |
%current% |
当前步数 |
%max% |
总步数 |
%bar% |
进度条图形 |
%percent% |
百分比 |
%elapsed% |
已用时间 |
%estimated% |
预计剩余时间 |
%memory% |
内存使用 |
3.2 自定义进度条字符
1 2 3
| $bar->setBarCharacter('='); $bar->setEmptyBarCharacter('-'); $bar->setProgressCharacter('>');
|
四、大数据量优化 - 降低刷新频率
默认每步刷新,处理几十万数据时控制台刷新开销较大。使用 setRedrawFrequency($steps) 降低刷新频率:
1 2 3 4 5 6 7 8
| $bar = $this->output->createProgressBar($total); $bar->setRedrawFrequency(100); $bar->start();
foreach ($userIds as $index => $id) { $bar->advance(); }
|
五、在进度条旁输出自定义消息
1 2 3 4 5 6 7 8 9 10
| $bar = $this->output->createProgressBar($total); $bar->start();
foreach ($userIds as $id) { $bar->setMessage("当前处理 ID: {$id}"); $bar->display(); $bar->advance(); }
|
注意:setMessage() 后需要调用 $bar->display() 才能立即看到变化,或者等待下一次 advance() 自动刷新。
六、Laravel 简化写法(无需手动创建对象)
1 2 3 4 5 6
| $this->output->progressStart($total); foreach ($userIds as $id) { $this->output->progressAdvance(); } $this->output->progressFinish();
|
这种方式内部自动创建并管理 ProgressBar,代码更简洁。
七、重要注意事项
| 问题 |
解决方法 |
混用 echo / dump 破坏进度条 |
如需输出日志,先调用 $bar->clear() 清除进度条,输出后再 $bar->display() |
advance() 步数总和 != $max |
确保累计前进步数等于总步数,否则百分比异常 |
| 异常退出时光标错位 |
在异常处理中调用 $bar->finish() |
| 大量数据导致内存溢出 |
使用 chunk() 或 cursor() 分批加载数据,配合进度条 |
八、完整示例(带异常处理)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| <?php
namespace App\Console\Commands;
use Illuminate\Console\Command; use App\Models\User;
class FixUserData extends Command { protected $signature = 'fix:user-data'; protected $description = '批量修复用户数据';
public function handle() { $total = User::where('status', 0)->count(); if ($total === 0) { $this->info('无需处理的数据'); return 0; }
$bar = $this->output->createProgressBar($total); $bar->setFormat(" %current%/%max% [%bar%] %percent:3s%%"); $bar->start();
$failedIds = [];
User::where('status', 0)->chunkById(200, function ($users) use ($bar, &$failedIds) { foreach ($users as $user) { try { // 模拟业务逻辑 $user->status = 1; $user->save(); } catch (\Exception $e) { $failedIds[] = $user->id; } $bar->advance(); } });
$bar->finish(); $this->newLine();
if (!empty($failedIds)) { $this->warn("失败 ID: " . implode(',', $failedIds)); } $this->info('处理完成'); return 0; } }
|
以上内容涵盖了 Laravel 中进度条的主要用法,可直接参考使用。