Console Commands
Warning: You are browsing the documentation for Symfony 5.x, which is no longer maintained.
Read the updated version of this page for Symfony 7.2 (the current stable version).
The Symfony framework provides lots of commands through the bin/console
script
(e.g. the well-known bin/console cache:clear
command). These commands are
created with the Console component. You can also
use it to create your own commands.
Running Commands
Each Symfony application comes with a large set of commands. You can use
the list
command to view all available commands in the application:
1 2 3 4 5 6 7 8 9 10 11 12 13
$ php bin/console list
...
Available commands:
about Display information about the current project
completion Dump the shell completion script
help Display help for a command
list List commands
assets
assets:install Install bundle's web assets under a public directory
cache
cache:clear Clear the cache
...
Note
list
is the default command, so running php bin/console
is the same.
If you find the command you need, you can run it with the --help
option
to view the command's documentation:
1
$ php bin/console assets:install --help
Note
--help
is one of the built-in global options from the Console component,
which are available for all commands, including those you can create.
To learn more about them, you can read
this section.
APP_ENV & APP_DEBUG
Console commands run in the environment defined in the APP_ENV
variable of the .env
file, which is dev
by default. It also reads the APP_DEBUG
value to turn "debug" mode on or off (it defaults to 1
, which is on).
To run the command in another environment or debug mode, edit the value of APP_ENV
and APP_DEBUG
. You can also define this env vars when running the
command, for instance:
1 2
# clears the cache for the prod environment
$ APP_ENV=prod php bin/console cache:clear
Console Completion
5.4
Console completion for Bash was introduced in Symfony 5.4.
If you are using the Bash shell, you can install Symfony's completion script to get auto completion when typing commands in the terminal. All commands support name and option completion, and some can even complete values.
First, make sure you installed and setup the "bash completion" package for
your OS (typically named bash-completion
). Then, install the Symfony
completion bash script once by running the completion
command in a
Symfony app installed on your computer:
1 2
$ php bin/console completion bash | sudo tee /etc/bash_completion.d/console-events-terminate
# after the installation, restart the shell
Now you are all set to use the auto completion for all Symfony Console applications on your computer. By default, you can get a list of complete options by pressing the Tab key.
Tip
Many PHP tools are built using the Symfony Console component (e.g. Composer, PHPstan and Behat). If they are using version 5.4 or higher, you can also install their completion script to enable console completion:
1
$ php vendor/bin/phpstan completion bash | sudo tee /etc/bash_completion.d/phpstan
Tip
If you are using the Symfony local web server, it is recommended to use the built-in completion
script that will ensure the right PHP version and configuration are used when
running the Console Completion. Run symfony completion --help
for the
installation instructions for your shell. The Symfony CLI will provide
completion for the console
and composer
commands.
Creating a Command
Commands are defined in classes extending Command. For example, you may want a command to create a user:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
// src/Command/CreateUserCommand.php
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class CreateUserCommand extends Command
{
// the name of the command (the part after "bin/console")
protected static $defaultName = 'app:create-user';
protected function execute(InputInterface $input, OutputInterface $output): int
{
// ... put here the code to create the user
// this method must return an integer number with the "exit status code"
// of the command. You can also use these constants to make code more readable
// return this if there was no problem running the command
// (it's equivalent to returning int(0))
return Command::SUCCESS;
// or return this if some error happened during the execution
// (it's equivalent to returning int(1))
// return Command::FAILURE;
// or return this to indicate incorrect command usage; e.g. invalid options
// or missing arguments (it's equivalent to returning int(2))
// return Command::INVALID
}
}
5.1
The Command::SUCCESS
and Command::FAILURE
constants were introduced
in Symfony 5.1.
5.3
The Command::INVALID
constant was introduced in Symfony 5.3
Configuring the Command
You can optionally define a description, help message and the
input options and arguments by overriding the
configure()
method:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// src/Command/CreateUserCommand.php
// ...
class CreateUserCommand extends Command
{
// the command description shown when running "php bin/console list"
protected static $defaultDescription = 'Creates a new user.';
// ...
protected function configure(): void
{
$this
// the command help shown when running the command with the "--help" option
->setHelp('This command allows you to create a user...')
;
}
}
Tip
Defining the $defaultDescription
static property instead of using the
setDescription()
method allows to get the command description without
instantiating its class. This makes the php bin/console list
command run
much faster.
If you want to always run the list
command fast, add the --short
option
to it (php bin/console list --short
). This will avoid instantiating command
classes, but it won't show any description for commands that use the
setDescription()
method instead of the static property.
5.3
The $defaultDescription
static property and the --short
option
were introduced in Symfony 5.3.
The configure()
method is called automatically at the end of the command
constructor. If your command defines its own constructor, set the properties
first and then call to the parent constructor, to make those properties
available in the configure()
method:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
// ...
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
class CreateUserCommand extends Command
{
// ...
public function __construct(bool $requirePassword = false)
{
// best practices recommend to call the parent constructor first and
// then set your own properties. That wouldn't work in this case
// because configure() needs the properties set in this constructor
$this->requirePassword = $requirePassword;
parent::__construct();
}
protected function configure(): void
{
$this
// ...
->addArgument('password', $this->requirePassword ? InputArgument::REQUIRED : InputArgument::OPTIONAL, 'User password')
;
}
}
Registering the Command
In PHP 8 and newer versions, you can register the command by adding the
AsCommand
attribute to it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// src/Command/CreateUserCommand.php
namespace App\Command;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
// the "name" and "description" arguments of AsCommand replace the
// static $defaultName and $defaultDescription properties
#[AsCommand(
name: 'app:create-user',
description: 'Creates a new user.',
hidden: false,
aliases: ['app:add-user']
)]
class CreateUserCommand extends Command
{
// ...
}
5.3
The ability to use PHP attributes to configure commands was introduced in Symfony 5.3.
If you can't use PHP attributes, register the command as a service and
tag it with the console.command
tag. If you're using the
default services.yaml configuration,
this is already done for you, thanks to autoconfiguration.
Running the Command
After configuring and registering the command, you can run it in the terminal:
1
$ php bin/console app:create-user
As you might expect, this command will do nothing as you didn't write any logic
yet. Add your own logic inside the execute()
method.
Console Output
The execute()
method has access to the output stream to write messages to
the console:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
// ...
protected function execute(InputInterface $input, OutputInterface $output): int
{
// outputs multiple lines to the console (adding "\n" at the end of each line)
$output->writeln([
'User Creator',
'============',
'',
]);
// the value returned by someMethod() can be an iterator (https://php.net/iterator)
// that generates and returns the messages with the 'yield' PHP keyword
$output->writeln($this->someMethod());
// outputs a message followed by a "\n"
$output->writeln('Whoa!');
// outputs a message without adding a "\n" at the end of the line
$output->write('You are about to ');
$output->write('create a user.');
return Command::SUCCESS;
}
Now, try executing the command:
1 2 3 4 5 6
$ php bin/console app:create-user
User Creator
============
Whoa!
You are about to create a user.
Output Sections
The regular console output can be divided into multiple independent regions called "output sections". Create one or more of these sections when you need to clear and overwrite the output information.
Sections are created with the ConsoleOutput::section() method, which returns an instance of ConsoleSectionOutput:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
// ...
use Symfony\Component\Console\Output\ConsoleOutputInterface;
class MyCommand extends Command
{
protected function execute(InputInterface $input, OutputInterface $output): int
{
if (!$output instanceof ConsoleOutputInterface) {
throw new \LogicException('This command accepts only an instance of "ConsoleOutputInterface".');
}
$section1 = $output->section();
$section2 = $output->section();
$section1->writeln('Hello');
$section2->writeln('World!');
sleep(1);
// Output displays "Hello\nWorld!\n"
// overwrite() replaces all the existing section contents with the given content
$section1->overwrite('Goodbye');
sleep(1);
// Output now displays "Goodbye\nWorld!\n"
// clear() deletes all the section contents...
$section2->clear();
sleep(1);
// Output now displays "Goodbye\n"
// ...but you can also delete a given number of lines
// (this example deletes the last two lines of the section)
$section1->clear(2);
sleep(1);
// Output is now completely empty!
return Command::SUCCESS;
}
}
Note
A new line is appended automatically when displaying information in a section.
Output sections let you manipulate the Console output in advanced ways, such as displaying multiple progress bars which are updated independently and appending rows to tables that have already been rendered.
Caution
Terminals only allow overwriting the visible content, so you must take into account the console height when trying to write/overwrite section contents.
Console Input
Use input options or arguments to pass information to the command:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
use Symfony\Component\Console\Input\InputArgument;
// ...
protected function configure(): void
{
$this
// configure an argument
->addArgument('username', InputArgument::REQUIRED, 'The username of the user.')
// ...
;
}
// ...
public function execute(InputInterface $input, OutputInterface $output): int
{
$output->writeln([
'User Creator',
'============',
'',
]);
// retrieve the argument value using getArgument()
$output->writeln('Username: '.$input->getArgument('username'));
return Command::SUCCESS;
}
Now, you can pass the username to the command:
1 2 3 4 5
$ php bin/console app:create-user Wouter
User Creator
============
Username: Wouter
See also
Read Console Input (Arguments & Options) for more information about console options and arguments.
Getting Services from the Service Container
To actually create a new user, the command has to access some
services. Since your command is already registered
as a service, you can use normal dependency injection. Imagine you have a
App\Service\UserManager
service that you want to access:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
// ...
use App\Service\UserManager;
use Symfony\Component\Console\Command\Command;
class CreateUserCommand extends Command
{
private $userManager;
public function __construct(UserManager $userManager)
{
$this->userManager = $userManager;
parent::__construct();
}
// ...
protected function execute(InputInterface $input, OutputInterface $output): int
{
// ...
$this->userManager->create($input->getArgument('username'));
$output->writeln('User successfully generated!');
return Command::SUCCESS;
}
}
Command Lifecycle
Commands have three lifecycle methods that are invoked when running the command:
- initialize() (optional)
-
This method is executed before the
interact()
and theexecute()
methods. Its main purpose is to initialize variables used in the rest of the command methods. - interact() (optional)
-
This method is executed after
initialize()
and beforeexecute()
. Its purpose is to check if some of the options/arguments are missing and interactively ask the user for those values. This is the last place where you can ask for missing required options/arguments. This method is called before validating the input. Note that it will not be called when the command is run without interaction (e.g. when passing the--no-interaction
global option flag). - execute() (required)
-
This method is executed after
interact()
andinitialize()
. It contains the logic you want the command to execute and it must return an integer which will be used as the command exit status.
Testing Commands
Symfony provides several tools to help you test your commands. The most useful one is the CommandTester class. It uses special input and output classes to ease testing without a real console:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
// tests/Command/CreateUserCommandTest.php
namespace App\Tests\Command;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Console\Tester\CommandTester;
class CreateUserCommandTest extends KernelTestCase
{
public function testExecute()
{
self::bootKernel();
$application = new Application(self::$kernel);
$command = $application->find('app:create-user');
$commandTester = new CommandTester($command);
$commandTester->execute([
// pass arguments to the helper
'username' => 'Wouter',
// prefix the key with two dashes when passing options,
// e.g: '--some-option' => 'option_value',
// use brackets for testing array value,
// e.g: '--some-option' => ['option_value'],
]);
$commandTester->assertCommandIsSuccessful();
// the output of the command in the console
$output = $commandTester->getDisplay();
$this->assertStringContainsString('Username: Wouter', $output);
// ...
}
}
If you are using a single-command application,
call setAutoExit(false)
on it to get the command result in CommandTester
.
5.2
The setAutoExit()
method for single-command applications was introduced
in Symfony 5.2.
5.4
The assertCommandIsSuccessful()
method was introduced in Symfony 5.4.
Tip
You can also test a whole console application by using ApplicationTester.
Caution
When testing commands using the CommandTester
class, console events are
not dispatched. If you need to test those events, use the
ApplicationTester instead.
Caution
When testing commands using the ApplicationTester class, don't forget to disable the auto exit flag:
1 2 3 4
$application = new Application();
$application->setAutoExit(false);
$tester = new ApplicationTester($application);
Caution
When testing InputOption::VALUE_NONE
command options, you must pass an
empty value to them:
1 2
$commandTester = new CommandTester($command);
$commandTester->execute(['--some-option' => '']);
Note
When using the Console component in a standalone project, use
Application
and extend the normal \PHPUnit\Framework\TestCase
.
When testing your commands, it could be useful to understand how your command reacts on different settings like the width and the height of the terminal. You have access to such information thanks to the Terminal class:
1 2 3 4 5 6 7 8 9
use Symfony\Component\Console\Terminal;
$terminal = new Terminal();
// gets the number of lines available
$height = $terminal->getHeight();
// gets the number of columns available
$width = $terminal->getWidth();
Logging Command Errors
Whenever an exception is thrown while running commands, Symfony adds a log
message for it including the entire failing command. In addition, Symfony
registers an event subscriber to listen to the
ConsoleEvents::TERMINATE event and adds a log
message whenever a command doesn't finish with the 0
exit status.
Using Events And Handling Signals
When a command is running, many events are dispatched, one of them allows to react to signals, read more in this section.
Learn More
- How to Call Other Commands
- How to Color and Style the Console Output
- How to Call a Command from a Controller
- How to Define Commands as Services
- How to Hide Console Commands
- Console Input (Arguments & Options)
- How to Make Commands Lazily Loaded
- Prevent Running the Same Console Command Multiple Times
- How to Style a Console Command
- Verbosity Levels
The console component also contains a set of "helpers" - different small tools capable of helping you with different tasks:
- Question Helper: interactively ask the user for information
- Formatter Helper: customize the output colorization
- Progress Bar: shows a progress bar
- Progress Indicator: shows a progress indicator
- Table: displays tabular data as a table
- Debug Formatter Helper: provides functions to output debug information when running an external program
- Process Helper: allows to run processes using
DebugFormatterHelper
- Cursor Helper: allows to manipulate the cursor in the terminal