Kevin Bond Javier Eguiluz
Contributed by Kevin Bond and Javier Eguiluz in #14057

Take a look at the code of any command that you've developed for your own Symfony applications. Odds are that its source code is "a mess" that mixes content with presentation. For example, to display a title in your command's output, you may have used any of these common alternatives:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// alternative 1
$formatter = $this->getHelperSet()->get('formatter');
$formattedBlock = $formatter->formatBlock('Lorem Ipsum Dolor Sit Amet', '', true);
$output->writeln($formattedBlock);

// alternative 2
$title = 'Lorem Ipsum Dolor Sit Amet';
$output->writeln('<info>'.$title.'</info>');
$output->writeln(str_repeat('=', strlen($title)));

// alternative 3
$output->writeln('');
$output->writeln('<info>Lorem Ipsum Dolor Sit Amet</>');
$output->writeln('<info>--------------------------</>');
$output->writeln('');

A few months ago we decided to improve this situation by introducing a new Style Guide for Symfony Commands. These styles are available in Symfony 2.7, but we really started using them in Symfony 2.8. Using a web application analogy, these styles allow you to create console commands which are semantic and forget about their styling and behavior. Your commands just define "the HTML" and the style guide is "the Bootstrap and jQuery" that brings them to life.

Using the new style guide in your commands is as easy as instantiating the SymfonyStyle class, passing to it the $input and $output of your command:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
namespace AppBundle\Command;

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

class MyCommand extends ContainerAwareCommand
{
    protected function configure()
    {
        // ...
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $io = new SymfonyStyle($input, $output);
        // ...
    }
}

We recommend you to name this variable $io because you will use it both for input and output operations. Following the same example shown above, this is how you can output a title in your commands:

1
$io->title('Lorem Ipsum Dolor Sit Amet');

Symfony will take care about the styling details for you: it will change the font color, it will add a newline before and after the title and it will display the title text underlined.

The style guide includes lots of shortcut methods for common needs, such as displaying a table:

1
2
3
4
5
6
7
$headers = ['Parameter', 'Value'];
$rows = [
    ['Param1', 'Value1'],
    ['Param2', 'Value2']
];

$io->table($headers, $rows);

The API of the style guide is concise, expressive and intuitive, to ease its learning curve:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$io = new SymfonyStyle($input, $output);

// common output elements
$io->title(string $message);
$io->section(string $message);
$io->text(string|array $message);
$io->comment(string|array $message);

// more advanced output elements
$io->note(string|array $message);
$io->caution(string|array $message);
$io->listing(array $elements);
$io->table(array $headers, array $rows);

// ask for user's input
$io->ask(string $question, string|null $default = null, callable|null $validator = null);
$io->askHidden(string $question, callable|null $validator = null);
$io->confirm(string $question, bool $default = true);
$io->choice(string $question, array $choices, string|int|null $default = null);

// display the result of the command or some important task
$io->success(string|array $message);
$io->error(string|array $message);
$io->warning(string|array $message);

In practice, this is how each of the above elements is displayed in the command output:

Symfony Console Style Guide

The main advantages of using this new Style Guide are:

  • It makes your commands appearance consistent, saving you lots of time deciding which styles to apply for each command.
  • It trims a lot of fat in your commands, shaving hundreds of lines dedicated to define the presentation of the information.
  • It only requires you to import one class (SymfonyStyle) instead of lots of different classes (Table, ProgressBar, ChoiceQuestion, ConfirmationQuestion, etc.)

Documentation is not ready yet for this style guide, but you can take a look at the source code of the built-in Symfony 2.8 or 3.0 commands, which have been completely redesigned.

Published in #Living on the edge