Console Commands
The Symfony framework provides lots of commands through thebin/console
script(e.g. the well-knownbin/console cache:clear
command). These commands arecreated with theConsole component. You can alsouse it to create your own commands.
Running Commands
Each Symfony application comes with a large set of commands. You can usethelist
command to view all available commands in the application:
12345678910111213
$php bin/console list...Available commands: about Display information about the current project completion Dump the shell completion scripthelp Displayhelpfor acommand 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 runningphp bin/console
is the same.
If you find the command you need, you can run it with the--help
optionto 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 readthis section.
APP_ENV & APP_DEBUG
Console commands run in theenvironment defined in theAPP_ENV
variable of the.env
file, which isdev
by default. It also reads theAPP_DEBUG
value to turn "debug" mode on or off (it defaults to1
, which is on).
To run the command in another environment or debug mode, edit the value ofAPP_ENV
andAPP_DEBUG
. You can also define this env vars when running thecommand, for instance:
12
# clears the cache for the prod environment$APP_ENV=prod php bin/console cache:clear
Console Completion
If you are using the Bash, Zsh or Fish shell, you can install Symfony'scompletion script to get auto completion when typing commands in theterminal. All commands support name and option completion, and some caneven complete values.

First, you have to install the completion scriptonce. Runbin/console completion --help
for the installation instructions foryour shell.
Note
When using Bash, make sure you installed and setup the "bash completion"package for your OS (typically namedbash-completion
).
After installing and restarting your terminal, you're all set to usecompletion (by default, 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:
12
$php vendor/bin/phpstan completion --help$composer completion --help
Tip
If you are using theSymfony local web server, it is recommended to use the built-in completionscript that will ensure the right PHP version and configuration are used whenrunning the Console Completion. Runsymfony completion --help
for theinstallation instructions for your shell. The Symfony CLI will providecompletion for theconsole
andcomposer
commands.
Creating a Command
Commands are defined in classes extendingCommand. For example, you maywant a command to create a user:
1234567891011121314151617181920212223242526272829303132
// src/Command/CreateUserCommand.phpnamespaceApp\Command;useSymfony\Component\Console\Attribute\AsCommand;useSymfony\Component\Console\Command\Command;useSymfony\Component\Console\Input\InputInterface;useSymfony\Component\Console\Output\OutputInterface;// the name of the command is what users type after "php bin/console"#[AsCommand(name:'app:create-user')]classCreateUserCommandextendsCommand{protectedfunctionexecute(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 }}
Configuring the Command
You can optionally define a description, help message and theinput options and arguments by overriding theconfigure()
method:
12345678910111213141516
// src/Command/CreateUserCommand.php// ...classCreateUserCommandextendsCommand{// ...protectedfunctionconfigure():void{$this// the command description shown when running "php bin/console list" ->setDescription('Creates a new user.')// the command help shown when running the command with the "--help" option ->setHelp('This command allows you to create a user...') ; }}
Tip
Using the#[AsCommand]
attribute to define a description instead ofusing thesetDescription()
method allows to get the command description withoutinstantiating its class. This makes thephp bin/console list
command runmuch faster.
If you want to always run thelist
command fast, add the--short
optionto it (php bin/console list --short
). This will avoid instantiating commandclasses, but it won't show any description for commands that use thesetDescription()
method instead of the attribute to define the commanddescription.
Theconfigure()
method is called automatically at the end of the commandconstructor. If your command defines its own constructor, set the propertiesfirst and then call to the parent constructor, to make those propertiesavailable in theconfigure()
method:
1234567891011121314151617181920212223242526
// ...useSymfony\Component\Console\Command\Command;useSymfony\Component\Console\Input\InputArgument;classCreateUserCommandextendsCommand{// ...publicfunction__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(); }protectedfunctionconfigure():void{$this// ... ->addArgument('password',$this->requirePassword ? InputArgument::REQUIRED : InputArgument::OPTIONAL,'User password') ; }}
Registering the Command
You can register the command by adding theAsCommand
attribute to it:
12345678910111213141516
// src/Command/CreateUserCommand.phpnamespaceApp\Command;useSymfony\Component\Console\Attribute\AsCommand;useSymfony\Component\Console\Command\Command;#[AsCommand(name:'app:create-user',description:'Creates a new user.',hidden:false,aliases: ['app:add-user'])]classCreateUserCommandextendsCommand{// ...}
If you can't use PHP attributes, register the command as a service andtag it with theconsole.command
tag. If you're using thedefault services.yaml configuration,this is already done for you, thanks toautoconfiguration.
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 logicyet. Add your own logic inside theexecute()
method.
Console Output
Theexecute()
method has access to the output stream to write messages tothe console:
1234567891011121314151617181920212223
// ...protectedfunctionexecute(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:
123456
$php bin/console app:create-userUser Creator============Whoa!You are about to create a user.
Output Sections
The regular console output can be divided into multiple independent regionscalled "output sections". Create one or more of these sections when you need toclear and overwrite the output information.
Sections are created with theConsoleOutput::section()method, which returns an instance ofConsoleSectionOutput:
1234567891011121314151617181920212223242526272829303132333435363738394041424344
// ...useSymfony\Component\Console\Output\ConsoleOutputInterface;classMyCommandextendsCommand{protectedfunctionexecute(InputInterface$input, OutputInterface$output):int{if (!$outputinstanceof ConsoleOutputInterface) {thrownew \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!// setting the max height of a section will make new lines replace the old ones$section1->setMaxHeight(2);$section1->writeln('Line1');$section1->writeln('Line2');$section1->writeln('Line3');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 asdisplaying multiple progress bars whichare updated independently andappending rows to tablesthat have already been rendered.
Warning
Terminals only allow overwriting the visible content, so you must take intoaccount the console height when trying to write/overwrite section contents.
Console Input
Use input options or arguments to pass information to the command:
1234567891011121314151617181920212223242526
useSymfony\Component\Console\Input\InputArgument;// ...protectedfunctionconfigure():void{$this// configure an argument ->addArgument('username', InputArgument::REQUIRED,'The username of the user.')// ... ;}// ...publicfunctionexecute(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:
12345
$php bin/console app:create-user WouterUser Creator============Username: Wouter
See also
ReadConsole Input (Arguments & Options) for more information about console options andarguments.
Getting Services from the Service Container
To actually create a new user, the command has to access someservices. Since your command is already registeredas a service, you can use normal dependency injection. Imagine you have aApp\Service\UserManager
service that you want to access:
12345678910111213141516171819202122232425
// ...useApp\Service\UserManager;useSymfony\Component\Console\Command\Command;classCreateUserCommandextendsCommand{publicfunction__construct(private UserManager$userManager, ){parent::__construct(); }// ...protectedfunctionexecute(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 thecommand:
- initialize()(optional)
- This method is executed before the
interact()
and theexecute()
methods. Its main purpose is to initialize variables used in the rest ofthe command methods. - interact()(optional)
- This method is executed after
initialize()
and beforeexecute()
.Its purpose is to check if some of the options/arguments are missingand interactively ask the user for those values. This is the last placewhere you can ask for missing required options/arguments. This method iscalled 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 mustreturn an integer which will be used as the commandexit status.
Testing Commands
Symfony provides several tools to help you test your commands. The mostuseful one is theCommandTesterclass. It uses special input and output classes to ease testing without a realconsole:
1234567891011121314151617181920212223242526272829303132333435
// tests/Command/CreateUserCommandTest.phpnamespaceApp\Tests\Command;useSymfony\Bundle\FrameworkBundle\Console\Application;useSymfony\Bundle\FrameworkBundle\Test\KernelTestCase;useSymfony\Component\Console\Tester\CommandTester;classCreateUserCommandTestextendsKernelTestCase{publicfunctiontestExecute():void{self::bootKernel();$application =newApplication(self::$kernel);$command =$application->find('app:create-user');$commandTester =newCommandTester($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 asingle-command application,callsetAutoExit(false)
on it to get the command result inCommandTester
.
Tip
You can also test a whole console application by usingApplicationTester.
Warning
When testing commands using theCommandTester
class, console events arenot dispatched. If you need to test those events, use theApplicationTester instead.
Warning
When testing commands using theApplicationTesterclass, don't forget to disable the auto exit flag:
1234
$application =newApplication();$application->setAutoExit(false);$tester =newApplicationTester($application);
Warning
When testingInputOption::VALUE_NONE
command options, you must passtrue
to them:
12
$commandTester =newCommandTester($command);$commandTester->execute(['--some-option' =>true]);
Note
When using the Console component in a standalone project, useApplicationand extend the normal\PHPUnit\Framework\TestCase
.
When testing your commands, it could be useful to understand how your commandreacts on different settings like the width and the height of the terminal, oreven the color mode being used. You have access to such information thanks to theTerminal class:
123456789101112131415
useSymfony\Component\Console\Terminal;$terminal =newTerminal();// gets the number of lines available$height =$terminal->getHeight();// gets the number of columns available$width =$terminal->getWidth();// gets the color mode$colorMode =$terminal->getColorMode();// changes the color mode$colorMode =$terminal->setColorMode(AnsiColorMode::Ansi24);
Logging Command Errors
Whenever an exception is thrown while running commands, Symfony adds a logmessage for it including the entire failing command. In addition, Symfonyregisters anevent subscriber to listen to theConsoleEvents::TERMINATE event and adds a logmessage whenever a command doesn't finish with the0
exit status.
Using Events And Handling Signals
When a command is running, many events are dispatched, one of them allows toreact to signals, read more inthis section.
Profiling Commands
Symfony allows to profile the execution of any command, including yours. First,make sure that thedebug mode and theprofilerare enabled. Then, add the--profile
option when running the command:
1
$php bin/console --profile app:my-command
Symfony will now collect data about the command execution, which is helpful todebug errors or check other issues. When the command execution is over, theprofile is accessible through the web page of the profiler.
Tip
If you run the command in verbose mode (adding the-v
option), Symfonywill display in the output a clickable link to the command profile (if yourterminal supports links). If you run it in debug verbosity (-vvv
) you'llalso see the time and memory consumed by the command.
Warning
When profiling themessenger:consume
command from theMessengercomponent, add the--no-reset
option to the command or you won't get anyprofile. Moreover, consider using the--limit
option to only process a fewmessages to make the profile more readable in the profiler.
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 smalltools 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 Helper: displays tabular data as a table
- Debug Formatter Helper: provides functions tooutput 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