Ebooks

Symfony Console Commands tutorial

Symfony Console Commands tutorial shows how to create console commands in Symfony. We are going to create a couple of commands in a console application.

Symfony

Symfony is a set of reusable PHP components and a PHP framework for web projects. Symfony was published as free software in 2005. The original author of Symfony is Fabien Potencier. Symfony was heavily inspired by the Spring Framework.

Symfony Console Component

Symfony Console component allows us to create command-line commands. The console commands can be used for creating cronjobs, imports, batch jobs, or some supportive tasks. Symfony console commands can be used in a Symfony console application or in a web application. In this tutorial, we will create commnads for a console application.

Symfony Console Command example

In the following example, we create Symfony console application using the Symfony Console component.

$ mkdir commands
$ cd commands

We create a project directory and locate into it.

$ composer require symfony/console

We install the console package.

composer.json
{
    "name": "Symfony command application",
    "description": 
    "This application demonstrates the usage of a Symfony command in a console application",
    "require": {
        "symfony/console": "^4.2"
    },
    "autoload": {
        "psr-4": {
            "App\\": "src"
        }
    }
}

We update the composer.json file. We enable autoloading of PHP classes located in the src directory under the App namespace.

$ composer dump-autoload -o

After the files are created, we need to call the composer dump-autoload -o command, which creates a file that maps classes to PHP files.

In the application, we are going to have five commands:

The commands are created in the src/Command directory. A commnad must extend Symfony\Component\Console\Command and implement its configure() and execute() methods.

Later, the command is added to a Symfony\Component\Console\Application with add().

src/Command/TimeCommand.php
<?php

namespace App\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class TimeCommand extends Command 
{
    protected function configure()
    {
        $this->setName('time')
        ->setDescription('Shows current date and time')
        ->setHelp('This command prints the current date and time');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $now = date('c');
        $message = sprintf("Current date and time: %s", $now);

        $output->writeln($message);
    }
}

The TimeCommand shows the current date and time.

protected function configure()
{
    $this->setName('time')
    ->setDescription('Shows current date and time')
    ->setHelp('This command prints the current date and time');
}

In the configure(), we set a name for the command with setName(). The name will be shown in the list of available commands. We also add description and help for the command.

protected function execute(InputInterface $input, OutputInterface $output)
{
    $now = date('c');
    $message = sprintf("Current date and time: %s", $now);

    $output->writeln($message);
}

The InputInterface is used for getting input from users and OutputInterface for displaying output. In our case, we get the current date and time with date() in standard ISO format and output it with writeln() to the console.

src/Command/MessageCommand.php
<?php

namespace App\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;

class MessageCommand extends Command
{
    protected function configure()
    {
        $this->setName('msg')
            ->setDescription('Prints a user provided message')
            ->setHelp('This command prints a message provided by the user')
            ->addArgument('msg', InputArgument::REQUIRED, 'Pass a message');
    }
 
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $message = sprintf('The message is: %s', $input->getArgument('msg'));
        $output->writeln($message);
    }
}

The MessageCommand prints the message retrieved from user's argument and outputs it to the console.

$this->setName('msg')
    ->setDescription('Prints a user provided message')
    ->setHelp('This command prints a message provided by the user')
    ->addArgument('msg', InputArgument::REQUIRED, 'Pass a message');

The argument can be either required or optional. The InputArgument::REQUIRED value makes the argument mandatory.

$message = sprintf('The message is: %s', $input->getArgument('msg'));
$output->writeln($message);

We retrieve the argument with getArgument() from the input and write it to the console with writeln().

src/Command/ColorCommand.php
<?php

namespace App\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;

class ColorCommand extends Command
{
    protected function configure()
    {
        $this->setName('colc')
            ->setDescription('Shows output in color')
            ->setHelp('This command shows output in color');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {

        $output->writeln("<info>Today is a windy day</info>");

        $outputStyle = new OutputFormatterStyle('red');
        $output->getFormatter()->setStyle('redt', $outputStyle);

        $output->writeln('<redt>Tomorrow will be snowing</redt>');
    }
}

The ColorCommand outputs text in color.

$output->writeln("<info>Today is a windy day</info>");

In this case, we use a built-in info format style.

$outputStyle = new OutputFormatterStyle('red');
$output->getFormatter()->setStyle('redt', $outputStyle);

$output->writeln('<redt>Tomorrow will be snowing</redt>');

We can also create custom output styles with OutputFormatterStyle. Our redt shows text in red color.

src/Command/BooksCommand.php
<?php

namespace App\Command;

use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class BooksCommand extends Command
{
    protected function configure() 
    {
        $this->setName('books')
            ->setDescription('Shows books in a table')
            ->setHelp('This command demonstrates the usage of a table helper');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $table = new Table($output);
        
        $table->setHeaderTitle('Books')
            ->setHeaders(['Title', 'ISBN', 'Author', 'Publisher'])
            ->setRows([
                ['Java Language Features', '978-1-4842-3347-4', 'Kishori Sharan', 'Apress' ],
                ['Python Testing with pytest', '978-1-68-050-240-4', 'Brian Okken', 'The Pragmatic Programmers' ],
                ['Deep Learning with Python', '978-1-61729-443-3', 'Francois Chollet', 'Manning' ],
                ['Laravel up & Running', '978-1-491-93698-5', 'Matt Stauffer', 'O\'Reilly' ],
                ['Sams Teach Yourself TCP/IP', '978-0-672-33789-5', 'Joe Casad', 'SAMS' ]
            ]);

          $table->render();
    }   
}

The BooksCommand uses a table helper to output data in a table format.

$table = new Table($output);

We create an instance of a Table helper.

$table->setHeaderTitle('Books')
    ->setHeaders(['Title', 'ISBN', 'Author', 'Publisher'])
    ->setRows([
        ['Java Language Features', '978-1-4842-3347-4', 'Kishori Sharan', 'Apress' ],
        ['Python Testing with pytest', '978-1-68-050-240-4', 'Brian Okken', 'The Pragmatic Programmers' ],
        ['Deep Learning with Python', '978-1-61729-443-3', 'Francois Chollet', 'Manning' ],
        ['Laravel up & Running', '978-1-491-93698-5', 'Matt Stauffer', 'O\'Reilly' ],
        ['Sams Teach Yourself TCP/IP', '978-0-672-33789-5', 'Joe Casad', 'SAMS' ]
    ]);

We build the table. A table header title is specified with setHeaderTitle(). The header names are specified with setHeaders(). Finally, the data are added with setRows().

$table->render();

The table is rendered with render().

src/Command/AskNameCommand.php
<?php

namespace App\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Question\Question;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class AskNameCommand extends Command
{
    protected function configure() 
    {
        $this->setName('ask')
            ->setDescription('Interactively asks name from the user')
            ->setHelp('This command asks a user name interactively and prints it');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $helper = $this->getHelper('question');
        $question = new Question("Enter your name: ", "guest");

        $name = $helper->ask($input, $output, $question);
        $message = sprintf("Hello %s!", $name);

        $output->writeln($message);
    }
}

The AskNameCommand uses the question helper to ask for user input.

$helper = $this->getHelper('question');

A question helper is created with getHelper().

$question = new Question("Enter your name: ", "guest");

A new Question question is created. The second parameter is the default value.

$name = $helper->ask($input, $output, $question);

The question is activate with ask(). The user input is stored in the $name variable.

$message = sprintf("Hello %s!", $name);

We build a message from the user input with sprintf().

$output->writeln($message);

Finally, the message is shown in the terminal with writeln().

A new Symfony application is created with Symfony\Component\Console\Application.

Application.php
<?php

require __DIR__ . '/vendor/autoload.php';

use App\Command\TimeCommand;
use App\Command\BooksCommand;
use App\Command\ColorCommand;
use App\Command\AskNameCommand;
use App\Command\MessageCommand;
use Symfony\Component\Console\Application;

$app = new Application();

$app->add(new MessageCommand());
$app->add(new TimeCommand());
$app->add(new AskNameCommand());
$app->add(new BooksCommand());
$app->add(new ColorCommand());

$app->run();

We create a Symfony console application with five commands.

$app = new Application();

A new console application is created.

$app->add(new MessageCommand());
$app->add(new TimeCommand());
$app->add(new AskNameCommand());
$app->add(new BooksCommand());
$app->add(new ColorCommand());

We add commands to the application.

$app->run();

The application is started with run().

$ php application.php list
Console Tool
...
Available commands:
    ask    Interactively asks name from the user
    books  Shows books in a table
    colc   Shows output in color
    help   Displays help for a command
    list   Lists commands
    msg    Prints a user provided message
    time   Shows current date and time

We can get a list of our commands.

$ php application.php books
+----------------------------+--------------- Books -----------------+---------------------------+
| Title                      | ISBN               | Author           | Publisher                 |
+----------------------------+--------------------+------------------+---------------------------+
| Java Language Features     | 978-1-4842-3347-4  | Kishori Sharan   | Apress                    |
| Python Testing with pytest | 978-1-68-050-240-4 | Brian Okken      | The Pragmatic Programmers |
| Deep Learning with Python  | 978-1-61729-443-3  | Francois Chollet | Manning                   |
| Laravel up & Running       | 978-1-491-93698-5  | Matt Stauffer    | O'Reilly                  |
| Sams Teach Yourself TCP/IP | 978-0-672-33789-5  | Joe Casad        | SAMS                      |
+----------------------------+--------------------+------------------+---------------------------+

We run the books command.

$ php application.php time
Current date and time: 2018-12-20T23:27:16+01:00

We run the time command.

In this tutorial, we have create five console commands in a Symfony console application.

$ php application.php ask
Enter your name: Peter
Hello Peter!

We run the ask command.

In this tutorial, we have create five console commands in a Symfony console application.

You might also be interested in the following related tutorials: Introduction to Symfony, Symfony validation tutorial, Symfony Flash messages, Symfony service tutorial, Symfony form tutorial, PHP tutorial.