Php Cli Progress Bar

I’ve been doing a lot of data manipulation on the command line recently, and one of bugbears that I ran into was that my commands gave no indication of how long they were going to take to complete.

Sick and tired of just looking at the blank screen I put together a small progress bar class that can be used indicate how many items have been processed.

class ProgressBar 
{

    protected $_spinners = ['|', '/', '-', '\\', '|', '/', '-', '\\'];

    /**
     * This is used to echo the progress of a task on the command line.
     * Pass in the current row that you are on and the number of rows that need to be processed and this will echo out
     * a progress bar like this
     *
     * Progress: [-----------------\                                           ]
     *
     * It is possible to change the width of the bar by passing in an int as the $steps param, otherwise this default
     * to 60
     *
     * Once the process is complete pass in the $last param as true to finish the the process bar
     *
     * @param      $totalDone - The number of rows that have been processed so far
     * @param      $total     - The total number of rows to be processed
     * @param bool $last      - If the process has been completed
     * @param bool $steps     - How wide the process bar should be
     */
    public function echoProgress($totalDone, $total, $last = false, $steps = false)
    {
        if (PHP_SAPI != 'cli') {
            return;
        }
        $steps = ($steps == false) ? 60 : $steps;
        if ($last === true) {
            $display = "Progress: [" . str_repeat('-', $steps + 1) . "]\r";
        } else {
            $toGo        = floor((1 - ($totalDone / $total)) * $steps);
            $progressBar = str_repeat('-', $steps - $toGo);
            $emptySpace  = str_repeat(' ', $toGo);
            $index       = $totalDone % 8;
            $display     = "Progress: [" . $progressBar . $this->_spinners[$index] . $emptySpace . "]\r";
        }
        // @codingStandardsIgnoreStart - There's nothing wrong with using echo on the CLI
        echo $display;
        // @codingStandardsIgnoreEnd
    }

}

This can then be used like so

$totalDone = 0;
$rowsToProcess = $this->getRowsToProcess();
$numberOfRowsToProcess = count($rowsToProcess);
$processBar = new ProcessBar();
foreach ($rowsToProcess as $row) {
    $this->processRow($row);
    $processBar->echoProgress(++$totalDone, $numberOfRowsToProcess);
}
$processBar->echoProgress(++$totalDone, $numberOfRowsToProcess, true);

Which will give the following output when run

ross@ross:~/localhost/tests $ php importData.php
starting the import of EdmondsCommerce\ProductImport\Model\OptionValues
starting the import of EdmondsCommerce\ProductImport\Model\Products
starting the import of EdmondsCommerce\ProductImport\Model\Combinations
Progress: [-----------------\                                           ]

Tags: clidebugging