◐ Shell
clean mode source ↗

Console Commands

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:

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:

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:

Console Completion

If you are using the Bash, Zsh or Fish 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.

The terminal completes the command name "secrets:remove" and the argument "SOME_OTHER_SECRET".

First, you have to install the completion script once. Run bin/console completion --help for the installation instructions for your shell.

Note

When using Bash, make sure you installed and setup the "bash completion" package for your OS (typically named bash-completion).

After installing and restarting your terminal, you're all set to use completion (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:

Creating a Command

Commands are defined in classes and auto-registered using the #[AsCommand] attribute. For example, you may want a command to create a user:

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.

8.1

Registering console commands by overriding the Bundle::registerCommands() method is deprecated. Use the #[AsCommand] attribute or the console.command service tag instead.

You can also use #[AsCommand] to add a description, usage examples, and longer help text for the command:

Additionally, you can extend the Command class to leverage advanced features like lifecycle hooks (e.g. initialize() and and interact()):

Method-based Commands

8.1

Support for method-based console commands was introduced in Symfony 8.1.

Instead of creating one class per command, you can define multiple commands in the same class by adding the #[AsCommand] attribute to individual public methods. This is useful to group related commands that share the same dependencies:

Each annotated method becomes an independent command that can be run, listed and tested separately.

Note

When using the Console component without the service container, you can register method-based commands manually:

Running the Command

After configuring and registering the command, you can run it in the terminal:

As you might expect, this command will do nothing as you didn't write any logic yet. Add your own logic inside the __invoke() method.

Command Aliases

You can define alternative names (aliases) for a command directly in its name using a pipe (|) separator. The first name in the list becomes the actual command name; the others are aliases that can also be used to run the command:

Console Output

The __invoke() method has access to the output stream to write messages to the console:

Now, try executing the command:

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:

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.

Warning

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:

Now, you can pass the username to the command:

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:

See also

Read Console Argument Value Resolvers for more information about advanced service injection features (such as #[Autowire], #[Target], and custom value resolvers).

Command Lifecycle

Commands have three lifecycle methods that are invoked when running the command:

initialize() (optional)
This method is executed before the interact() and the execute() 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 before execute(). 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).
__invoke() (or execute()) (required)
This method is executed after interact() and initialize(). 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

In test classes extending KernelTestCase, Symfony provides the runCommand() method to run console commands and inspect their results. Some assertions are also provided by the ConsoleCommandAssertionsTrait to check the command executions status:

8.1

The runCommand() method and the ExecutionResult class were introduced in Symfony 8.1.

The ExecutionResult object gives access to stdout, stderr and the combined display separately:

You can also assert multiple expectations at once using assertCommandResultEquals():

If your command requires interactive inputs, pass them as the third argument:

Warning

When testing commands using the CommandTester class, console events are not dispatched. If you need to test those events, use the ApplicationTester instead.

Note

When using the Console component in a standalone project (without the Symfony framework), extend \PHPUnit\Framework\TestCase instead of KernelTestCase and use Application instead of the FrameworkBundle one.

Testing Console Applications

In addition to testing single commands, you can test full console applications with the ApplicationTester class:

Note

Don't forget to call setAutoExit(false) on the application before passing it to ApplicationTester. Without it, the application calls exit() after running the command, which would terminate the PHPUnit process.

Legacy Command Tester

Using the runCommand() method from KernelTestCase is the recommended way of testing commands in Symfony applications. However, you can also use the CommandTester class directly, which is useful when testing commands outside the Symfony framework or when you need lower-level control over the testing setup:

Note

If you are using a single-command application, call setAutoExit(false) on the application to get the command result in CommandTester.

Warning

When testing InputOption::VALUE_NONE command options, you must pass true to them:

Note

The CommandTester class does not implement ConsoleOutputInterface, so methods like section() are not directly accessible. To test them, use the capture_stderr_separately option of the execute() method:

Getting Terminal Information

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, or even the color mode being used. You have access to such information thanks to the Terminal class:

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 you to react to signals, read more in this section.

Profiling Commands

Symfony allows you to profile the execution of any command, including yours. First, make sure that the debug mode and the profiler are enabled. Then, add the --profile option when running the command:

Symfony will now collect data about the command execution, which is helpful to debug errors or check other issues. When the command execution is over, the profile is accessible through the web page of the profiler.

Among the collected data, the performance panel displays the duration of each argument value resolver used during the command execution, which helps spot slow resolvers.

8.1

The tracing of console argument value resolvers in the profiler's performance panel was introduced in Symfony 8.1.

Tip

If you run the command in verbose mode (adding the -v option), Symfony will display in the output a clickable link to the command profile (if your terminal supports links). If you run it in debug verbosity (-vvv) you'll also see the time and memory consumed by the command.

Warning

When profiling the messenger:consume command from the Messenger component, add the --no-reset option to the command or you won't get any profile. Moreover, consider using the --limit option to only process a few messages to make the profile more readable in the profiler.

Legacy Syntax to Define Commands

Instead of using invokable commands, you can also define commands by extending the Command class. Both syntaxes are supported, but invokable commands are recommended:

You can optionally define a description, help message and the input options and arguments by overriding the configure() method:

Tip

Using the #[AsCommand] attribute to define a description instead of the setDescription() method retrieves the command description without instantiating its class, which makes the php bin/console list command run much faster.

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:

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.