Laravel 5.1 - How to set a message on progress bar

Christopher picture Christopher · Aug 14, 2015 · Viewed 10k times · Source

I'm trying the same example as provided on Laravel docs:

$users = App\User::all();

$this->output->progressStart(count($users));

foreach ($users as $user) {
    print "$user->name\n";

    $this->output->progressAdvance();
}

$this->output->progressFinish();

And this works well. I want to customize the progress bar (see this) but $this->output->setMessage('xpto'); gives:

PHP Fatal error:  Call to undefined method Illuminate\Console\OutputStyle::setFormat()

Answer

Rafael Beckel picture Rafael Beckel · Aug 14, 2015

The $this->output object is a instance of Symfony's Symfony\Component\Console\Style\SymfonyStyle, which provides the methods progressStart(), progressAdvance() and progressFinish().

The progressStart() method dynamically creates an instance of Symfony\Component\Console\Helper\ProgressBar object and appends it to your output object, so you can manipulate it using progressAdvance() and progressFinish().

Unfortunatelly, Symfony guys decided to keep both $progressBar property and getProgressBar() method as private, so you can't access the actual ProgressBar instance directly via your output object if you used progressStart() to start it.

createProgressBar() to the rescue!

However, there's a cool undocumented method called createProgressBar($max) that returns you a shiny brand new ProgressBar object that you can play with.

So, you can just do:

$progress = this->output->createProgressBar(100);

And do whatever you want with it using the Symfony's docs page you provided. For example:

$this->info("Creating progress bar...\n");

$progress = $this->output->createProgressBar(100);

$progress->setFormat("%message%\n %current%/%max% [%bar%] %percent:3s%%");

$progress->setMessage("100? I won't count all that!");
$progress->setProgress(60);

for ($i = 0;$i<40;$i++) {
    sleep(1);
    if ($i == 90) $progress->setMessage('almost there...');
    $progress->advance();
}

$progress->finish();

Hope it helps. ;)