Search code examples
phplaravelsymfonylaravel-5laravel-artisan

Laravel - How to set a message on progress bar


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()

Solution

  • The object returned by $this->command->getOutput() 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().

    Unfortunately, Symfony maintainers decided to keep both the $progressBar property and the 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 an undocumented method called createProgressBar($max) that returns you a shiny brand new ProgressBar object that you can play with.

    So, you can just do the following:

    $progress = $this->command->getOutput()->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->command->getOutput()->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();
    

    I hope it helps. ;)