Jak na progress bar v konzolové aplikaci se Symfony

Symfony neslouží pouze pro stavbu klasických webů, ale můžete v ní vytvářet také konzolové aplikace. I kdyby sloužily jen k ovládání vašeho projektu přes příkazový řádek. Ukážeme si jednoduchou konzolovou aplikaci s grafickým ukazatelem průběhu déle trvající operace.

Console v PHP frameworku Symfony je něco jako například Drush pro Drupal nebo WP-CLI pro WordPress. Tedy nástroj pro ovládání webu z příkazového řádku. Hodí se pro spouštění jednorázových operací jako jsou vstupní importy dat, nebo pro periodické spouštění operací v aplikaci pomocí plánovače procesů v systému.

S konzolí samozřejmě pracujete i během vývoje. Pokud se vám líbí všechny ty generátory kódu, vytváření a migrace databází, tak vězte, že velmi snadno si napíšete i vlastní příkaz pro Symfony Console.

V tomto článku si ukážeme vytvoření jednoduché konzolové aplikace v Symfony, která zobrazí průběh práce pomocí progress baru. V další iteraci si ukážeme, jak výstup konzolové aplikace obarvit, a nakonec vyzkoušíme zapojení grafiky místo textového znázornění progress baru. 

Vytvořte si tedy nový projekt na hraní a pustíme se do toho:
symfony new progress

Základní konzolová aplikace v Symfony

Naše vzorová aplikace bude spouštěna příkazem bin/console import. Řekněme, že třeba poslouží pro jednorázový import dat do webu z nějaké jiné databáze. Samotnou operaci zde jenom nasimulujeme, cílem je ukázat si kostru a práci s progress barem.

Výsledný kód:

<?php

namespace App\Command;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Helper\ProgressBar;

#[AsCommand(
    name: 'import',
    description: 'Ukázka déle trvající operace s progress barem',
)]

class ImportCommand extends Command

{
    public function __construct()
    {
        parent::__construct();
    }

    protected function configure(): void
    {
        $this
            ->setDescription('Ukázka déle trvající operace s progress barem');
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $startTime = microtime(true);
        $totalRows = 123;
        $progressBar = new ProgressBar($output, $totalRows);
        $progressBar->start();
        $processedCount = 0;
        for ($i = 0; $i < $totalRows; $i++) {
           usleep(10000);
           $processedCount++;
           $progressBar->advance();
        }
        $progressBar->finish();
        $endTime = microtime(true);
        $executionTime = $endTime - $startTime;
        $output->writeln("\nImport hotov. Zpracováno záznamů: $processedCount");
        $output->writeln("Délka zpracování: " . round($executionTime, 2) . " sekund.");
        return Command::SUCCESS;
    }
}
Image
Symfony ProgressBar v základní podobě
Symfony ProgressBar v základní podobě

Jak na barevný výstup do terminálu

Základní výstup máme, ale Symfony se neomezuje pouze na něj, dovede pracovat s barvami tak, aby zobrazované informace byly přehlednější.

<?php

namespace App\Command;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Style\SymfonyStyle;

#[AsCommand(
    name: 'import',
    description: 'Ukázka déle trvající operace s progress barem',
)]

class ImportCommand extends Command
{

    public function __construct()
    {
        parent::__construct();
    }

    protected function configure(): void
    {
        $this
            ->setDescription('Ukázka déle trvající operace s progress barem');
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $io->title('Zahajuji import studijních programů');
        $startTime = microtime(true);
        $totalRows = 123;
        
        $progressBar = $io->createProgressBar($totalRows);
        $progressBar->setFormat(' [%bar%] %current%/%max% | %percent:3s%% | %elapsed:6s%');
        $progressBar->setBarCharacter('<info>=</info>');
        $progressBar->setEmptyBarCharacter('<error>-</error>');
        $progressBar->setProgressCharacter('<comment>></comment>');
        
        $progressBar->start();
        $processedCount = 0;
        
        for ($i = 0; $i < $totalRows; $i++) {
            usleep(100000);
            $processedCount++;
            $progressBar->advance();
        }
        
        $progressBar->finish();
        $endTime = microtime(true);
        $executionTime = $endTime - $startTime;
        
        $io->newLine(2);
        $io->success("Import hotov. Celkem záznamů: $processedCount");
        $io->text("Čas zpracování: " . round($executionTime, 2) . " sekund.");
        
        return Command::SUCCESS;
    }
}
Image
Symfony ProgressBar v barevné podobě
Symfony ProgressBar v barevné podobě

Grafický ukazatel průběhu práce

Předchozí úprava už je celkem přehledná, barvy nám oddělují zobrazení důležitých informací. Na záběr si ještě ukážeme zobrazení progress baru, který pracuje s grafickým výstupem místo se znakem rovnítka.

Nová úprava zahrnuje pouze změnu v nastavování vlastností po vytvoření progress baru:

$progressBar->setBarWidth(50);
$progressBar->setFormat('<bg=green;fg=white> %current%/%max% [%bar%] %percent:3s%% %elapsed:6s% </>');
$progressBar->setEmptyBarCharacter(' ');
$progressBar->setProgressCharacter('>');
$progressBar->setBarCharacter('<bg=blue> </>');
Image
Symfony ProgressBar v grafické podobě
Symfony ProgressBar v grafické podobě

S výstupy z konzolové aplikace v Symfony si můžeme docela vyhrát a když jsem progress bar použil kdysi poprvé, překvapilo mě, jak snadné je díky Symfony zobrazovat na příkazovém řádku průběh zpracování dat nebo jakékoli jiné déle trvající operace.

Další materiály najdete samozřejmě na stránkách dokumentace. Kromě tohoto klasického průběhového ukazatele má Symfony též Progress Indicator, který využijete ve chvíli, kdy nelze určit délku operace, ale potřebujete ukázat uplynulý čas a dát uživateli najevo, že aplikace stále pracuje.

Tagy

Buďme ve spojení, přihlaste se k newsletteru

Odesláním formuláře souhlasíte s podmínkami zpracováním osobních údajů. 
Více informací v Ochrana osobních údajů.

Autor článku: Jan Polzer

Tvůrce webů z Brna se specializací na Drupal, WordPress a Symfony. Acquia Certified Developer & Site Builder. Autor několika knih o Drupalu.
Web Development Director v Lesensky.cz. Ve volných chvílích podnikám výlety na souši i po vodě. Více se dozvíte na polzer.cz a mém LinkedIn profilu.

Komentáře k článku

Přidat komentář

Odesláním komentáře souhlasíte s podmínkami Ochrany osobních údajů

reklama
Moje kniha o CMS Drupal

 

Kniha 333 tipů a triků pro Drupal 9


Více na KnihyPolzer.cz

Sledujte Maxiorla na Facebooku

Maxiorel na Facebooku

Hosting pro Drupal a WordPress

Hledáte český webhosting vhodný nejenom pro redakční systém Drupal? Tak vyzkoušejte Webhosting C4 za 1200 Kč na rok s doménou v ceně, 20 GB prostoru a automatické navyšováním o 2 GB každý rok. Podrobnosti zde.

@maxiorel na Twitteru

Maxiorel na Twitteru