|
| 1 | +.. index:: |
| 2 | + single: Console Helpers; Progress Bar |
| 3 | + |
| 4 | +Progress Bar |
| 5 | +============ |
| 6 | + |
| 7 | +.. versionadded:: 2.5 |
| 8 | + The Progress Bar feature was introduced in Symfony 2.5 as a replacement for |
| 9 | + the :doc:`Progress Helper </components/console/helpers/progresshelper>`. |
| 10 | + |
| 11 | +When executing longer-running commands, it may be helpful to show progress |
| 12 | +information, which updates as your command runs: |
| 13 | + |
| 14 | +.. image:: /images/components/console/progressbar.gif |
| 15 | + |
| 16 | +To display progress details, use the |
| 17 | +:class:`Symfony\\Component\\Console\\Helper\\ProgressBar`, pass it a total |
| 18 | +number of units, and advance the progress as the command executes:: |
| 19 | + |
| 20 | + use Symfony\Component\Console\Helper\ProgressBar; |
| 21 | + |
| 22 | + // create a new progress bar (50 units) |
| 23 | + $progress = new ProgressBar($output, 50); |
| 24 | + |
| 25 | + // start and displays the progress bar |
| 26 | + $progress->start(); |
| 27 | + |
| 28 | + $i = 0; |
| 29 | + while ($i++ < 50) { |
| 30 | + // ... do some work |
| 31 | + |
| 32 | + // advance the progress bar 1 unit |
| 33 | + $progress->advance(); |
| 34 | + |
| 35 | + // you can also advance the progress bar by more than 1 unit |
| 36 | + // $progress->advance(3); |
| 37 | + } |
| 38 | + |
| 39 | + // ensure that the progress bar is at 100% |
| 40 | + $progress->finish(); |
| 41 | + |
| 42 | +Instead of advancing the bar by a number of steps (with the |
| 43 | +:method:`Symfony\\Component\\Console\\Helper\\ProgressBar::advance` method), |
| 44 | +you can also set the current progress by calling the |
| 45 | +:method:`Symfony\\Component\\Console\\Helper\\ProgressBar::setCurrent` method. |
| 46 | + |
| 47 | +.. caution:: |
| 48 | + |
| 49 | + The progress bar only works if your platform supports ANSI codes; on other |
| 50 | + platforms, no output is generated. |
| 51 | + |
| 52 | +If you don't know the number of steps in advance, just omit the steps argument |
| 53 | +when creating the :class:`Symfony\\Component\\Console\\Helper\\ProgressBar` |
| 54 | +instance:: |
| 55 | + |
| 56 | + $progress = new ProgressBar($output); |
| 57 | + |
| 58 | +The progress will then be displayed as a throbber:: |
| 59 | + |
| 60 | +.. code-block:: text |
| 61 | +
|
| 62 | + # no max steps (displays it like a throbber) |
| 63 | + 0 [>---------------------------] |
| 64 | + 5 [----->----------------------] |
| 65 | + 5 [============================] |
| 66 | +
|
| 67 | + # max steps defined |
| 68 | + 0/3 [>---------------------------] 0% |
| 69 | + 1/3 [=========>------------------] 33% |
| 70 | + 3/3 [============================] 100% |
| 71 | +
|
| 72 | +Whenever your task is finished, don't forget to call |
| 73 | +:method:`Symfony\\Component\\Console\\Helper\\ProgressBar::finish` to ensure |
| 74 | +that the progress bar display is refreshed with a 100% completion. |
| 75 | + |
| 76 | +.. note:: |
| 77 | + |
| 78 | + If you want to output something while the progress bar is running, |
| 79 | + call :method:`Symfony\\Component\\Console\\Helper\\ProgressBar::clear` first. |
| 80 | + After you're done, call |
| 81 | + :method:`Symfony\\Component\\Console\\Helper\\ProgressBar::display` |
| 82 | + to show the progress bar again. |
| 83 | + |
| 84 | +Customizing the Progress Bar |
| 85 | +---------------------------- |
| 86 | + |
| 87 | +Built-in Formats |
| 88 | +~~~~~~~~~~~~~~~~ |
| 89 | + |
| 90 | +By default, the information rendered on a progress bar depends on the current |
| 91 | +level of verbosity of the ``OutputInterface`` instance: |
| 92 | + |
| 93 | +.. code-block:: text |
| 94 | +
|
| 95 | + # OutputInterface::VERBOSITY_NORMAL (CLI with no verbosity flag) |
| 96 | + 0/3 [>---------------------------] 0% |
| 97 | + 1/3 [=========>------------------] 33% |
| 98 | + 3/3 [============================] 100% |
| 99 | +
|
| 100 | + # OutputInterface::VERBOSITY_VERBOSE (-v) |
| 101 | + 0/3 [>---------------------------] 0% 1 sec |
| 102 | + 1/3 [=========>------------------] 33% 1 sec |
| 103 | + 3/3 [============================] 100% 1 sec |
| 104 | +
|
| 105 | + # OutputInterface::VERBOSITY_VERY_VERBOSE (-vv) |
| 106 | + 0/3 [>---------------------------] 0% 1 sec |
| 107 | + 1/3 [=========>------------------] 33% 1 sec |
| 108 | + 3/3 [============================] 100% 1 sec |
| 109 | +
|
| 110 | + # OutputInterface::VERBOSITY_DEBUG (-vvv) |
| 111 | + 0/3 [>---------------------------] 0% 1 sec/1 sec 1.0 MB |
| 112 | + 1/3 [=========>------------------] 33% 1 sec/1 sec 1.0 MB |
| 113 | + 3/3 [============================] 100% 1 sec/1 sec 1.0 MB |
| 114 | +
|
| 115 | +.. note:: |
| 116 | + |
| 117 | + If you call a command with the quiet flag (``-q``), the progress bar won't |
| 118 | + be displayed. |
| 119 | + |
| 120 | +Instead of relying on the verbosity mode of the current command, you can also |
| 121 | +force a format via ``setFormat()``:: |
| 122 | + |
| 123 | + $bar->setFormat('verbose'); |
| 124 | + |
| 125 | +The built-in formats are the following: |
| 126 | + |
| 127 | +* ``normal`` |
| 128 | +* ``verbose`` |
| 129 | +* ``very_verbose`` |
| 130 | +* ``debug`` |
| 131 | + |
| 132 | +If you don't set the number of steps for your progress bar, use the ``_nomax`` |
| 133 | +variants: |
| 134 | + |
| 135 | +* ``normal_nomax`` |
| 136 | +* ``verbose_nomax`` |
| 137 | +* ``very_verbose_nomax`` |
| 138 | +* ``debug_nomax`` |
| 139 | + |
| 140 | +Custom Formats |
| 141 | +~~~~~~~~~~~~~~ |
| 142 | + |
| 143 | +Instead of using the built-in formats, you can also set your own:: |
| 144 | + |
| 145 | + $bar->setFormat('%bar%'); |
| 146 | + |
| 147 | +This sets the format to only display the progress bar itself: |
| 148 | + |
| 149 | +.. code-block:: text |
| 150 | +
|
| 151 | + >--------------------------- |
| 152 | + =========>------------------ |
| 153 | + ============================ |
| 154 | +
|
| 155 | +A progress bar format is a string that contains specific placeholders (a name |
| 156 | +enclosed with the ``%`` character); the placeholders are replaced based on the |
| 157 | +current progress of the bar. Here is a list of the built-in placeholders: |
| 158 | + |
| 159 | +* ``current``: The current step; |
| 160 | +* ``max``: The maximum number of steps (or 0 if no max is defined); |
| 161 | +* ``bar``: The bar itself; |
| 162 | +* ``percent``: The percentage of completion (not available if no max is defined); |
| 163 | +* ``elapsed``: The time elapsed since the start of the progress bar; |
| 164 | +* ``remaining``: The remaining time to complete the task (not available if no max is defined); |
| 165 | +* ``estimated``: The estimated time to complete the task (not available if no max is defined); |
| 166 | +* ``memory``: The current memory usage; |
| 167 | +* ``message``: The current message attached to the progress bar. |
| 168 | + |
| 169 | +For instance, here is how you could set the format to be the same as the |
| 170 | +``debug`` one:: |
| 171 | + |
| 172 | + $bar->setFormat(' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%'); |
| 173 | + |
| 174 | +Notice the ``:6s`` part added to some placeholders? That's how you can tweak |
| 175 | +the appearance of the bar (formatting and alignment). The part after the colon |
| 176 | +(``:``) is used to set the ``sprintf`` format of the string. |
| 177 | + |
| 178 | +The ``message`` placeholder is a bit special as you must set the value |
| 179 | +yourself:: |
| 180 | + |
| 181 | + $bar->setMessage('Task starts'); |
| 182 | + $bar->start(); |
| 183 | + |
| 184 | + $bar->setMessage('Task in progress...'); |
| 185 | + $bar->advance(); |
| 186 | + |
| 187 | + // ... |
| 188 | + |
| 189 | + $bar->setMessage('Task is finished'); |
| 190 | + $bar->finish(); |
| 191 | + |
| 192 | +Instead of setting the format for a given instance of a progress bar, you can |
| 193 | +also define global formats:: |
| 194 | + |
| 195 | + ProgressBar::setFormatDefinition('minimal', 'Progress: %percent%%'); |
| 196 | + |
| 197 | + $bar = new ProgressBar($output, 3); |
| 198 | + $bar->setFormat('minimal'); |
| 199 | + |
| 200 | +This code defines a new ``minimal`` format that you can then use for your |
| 201 | +progress bars: |
| 202 | + |
| 203 | +.. code-block:: text |
| 204 | +
|
| 205 | + Progress: 0% |
| 206 | + Progress: 33% |
| 207 | + Progress: 100% |
| 208 | +
|
| 209 | +.. tip:: |
| 210 | + |
| 211 | + It is almost always better to redefine built-in formats instead of creating |
| 212 | + new ones as that allows the display to automatically vary based on the |
| 213 | + verbosity flag of the command. |
| 214 | + |
| 215 | +When defining a new style that contains placeholders that are only available |
| 216 | +when the maximum number of steps is known, you should create a ``_nomax`` |
| 217 | +variant:: |
| 218 | + |
| 219 | + ProgressBar::setFormatDefinition('minimal', '%percent%% %remaining%'); |
| 220 | + ProgressBar::setFormatDefinition('minimal_nomax', '%percent%%'); |
| 221 | + |
| 222 | + $bar = new ProgressBar($output); |
| 223 | + $bar->setFormat('minimal'); |
| 224 | + |
| 225 | +When displaying the progress bar, the format will automatically be set to |
| 226 | +``minimal_nomax`` if the bar does not have a maximum number of steps like in |
| 227 | +the example above. |
| 228 | + |
| 229 | +.. tip:: |
| 230 | + |
| 231 | + A format can contain any valid ANSI codes and can also use the |
| 232 | + Symfony-specific way to set colors:: |
| 233 | + |
| 234 | + ProgressBar::setFormatDefinition( |
| 235 | + 'minimal', |
| 236 | + '<info>%percent%</info>\033[32m%\033[0m <fg=white;bg=blue>%remaining%</>' |
| 237 | + ); |
| 238 | + |
| 239 | +.. note:: |
| 240 | + |
| 241 | + A format can span more than one line; that's very useful when you want to |
| 242 | + display more contextual information alongside the progress bar (see the |
| 243 | + example at the beginning of this article). |
| 244 | + |
| 245 | +Bar Settings |
| 246 | +~~~~~~~~~~~~ |
| 247 | + |
| 248 | +Amongst the placeholders, ``bar`` is a bit special as all the characters used |
| 249 | +to display it can be customized:: |
| 250 | + |
| 251 | + // the finished part of the bar |
| 252 | + $progress->setBarCharacter('<comment>=</comment>'); |
| 253 | + |
| 254 | + // the unfinished part of the bar |
| 255 | + $progress->setEmptyBarCharacter(' '); |
| 256 | + |
| 257 | + // the progress character |
| 258 | + $progress->setProgressCharacter('|'); |
| 259 | + |
| 260 | + // the bar width |
| 261 | + $progress->setBarWidth(50); |
| 262 | + |
| 263 | +.. caution:: |
| 264 | + |
| 265 | + For performance reasons, be careful if you set the total number of steps |
| 266 | + to a high number. For example, if you're iterating over a large number of |
| 267 | + items, consider setting the redraw frequency to a higher value by calling |
| 268 | + :method:`Symfony\\Component\\Console\\Helper\\ProgressHelper::setRedrawFrequency`, |
| 269 | + so it updates on only some iterations:: |
| 270 | + |
| 271 | + $progress->start($output, 50000); |
| 272 | + |
| 273 | + // update every 100 iterations |
| 274 | + $progress->setRedrawFrequency(100); |
| 275 | + |
| 276 | + $i = 0; |
| 277 | + while ($i++ < 50000) { |
| 278 | + // ... do some work |
| 279 | + |
| 280 | + $progress->advance(); |
| 281 | + } |
| 282 | + |
| 283 | +Custom Placeholders |
| 284 | +~~~~~~~~~~~~~~~~~~~ |
| 285 | + |
| 286 | +If you want to display some information that depends on the progress bar |
| 287 | +display that are not available in the list of built-in placeholders, you can |
| 288 | +create your own. Let's see how you can create a ``remaining_steps`` placeholder |
| 289 | +that displays the number of remaining steps:: |
| 290 | + |
| 291 | + ProgressBar::setPlaceholderFormatter( |
| 292 | + '%remaining_steps%', |
| 293 | + function (ProgressBar $bar, OutputInterface $output) { |
| 294 | + return $bar->getMaxSteps() - $bar->getStep(); |
| 295 | + } |
| 296 | + ); |
| 297 | + |
| 298 | +Custom Messages |
| 299 | +~~~~~~~~~~~~~~~ |
| 300 | + |
| 301 | +The ``%message%`` placeholder allows you to specify a custom message to be |
| 302 | +displayed with the progress bar. But if you need more than one, just define |
| 303 | +your own:: |
| 304 | + |
| 305 | + $bar->setMessage('Task starts'); |
| 306 | + $bar->setMessage('', 'filename'); |
| 307 | + $bar->start(); |
| 308 | + |
| 309 | + $bar->setMessage('Task is in progress...'); |
| 310 | + while ($file = array_pop($files)) { |
| 311 | + $bar->setMessage($filename, 'filename'); |
| 312 | + $bar->advance(); |
| 313 | + } |
| 314 | + |
| 315 | + $bar->setMessage('Task is finished'); |
| 316 | + $bar->setMessage('', 'filename'); |
| 317 | + $bar->finish(); |
| 318 | + |
| 319 | +For the ``filename`` to be part of the progress bar, just add the |
| 320 | +``%filename%`` placeholder in your format:: |
| 321 | + |
| 322 | + $bar->setFormat(" %message%\n %step%/%max%\n Working on %filename%"); |
0 commit comments