Suppose you want to confirm an action before actually executing it. Add
the following to your command:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

// ...useSymfony\Component\Console\Input\InputInterface;useSymfony\Component\Console\Output\OutputInterface;useSymfony\Component\Console\Question\ConfirmationQuestion;classYourCommandextendsCommand{// ...publicfunctionexecute(InputInterface$input,OutputInterface$output){$helper=$this->getHelper('question');$question=newConfirmationQuestion('Continue with this action?',false);if(!$helper->ask($input,$output,$question)){return;}}}

In this case, the user will be asked "Continue with this action?". If the user
answers with y it returns true or false if they answer with n.
The second argument to
__construct()
is the default value to return if the user doesn't enter any valid input. If
the second argument is not provided, true is assumed.

Tip

You can customize the regex used to check if the answer means "yes" in the
third argument of the constructor. For instance, to allow anything that
starts with either y or j, you would set it to:

1
2
3
4
5

$question=newConfirmationQuestion('Continue with this action?',false,'/^(y|j)/i');

You can also ask a question with more than a simple yes/no answer. For instance,
if you want to know a bundle name, you can add this to your command:

1
2
3
4
5
6
7
8
9
10

useSymfony\Component\Console\Question\Question;// ...publicfunctionexecute(InputInterface$input,OutputInterface$output){// ...$question=newQuestion('Please enter the name of the bundle','AcmeDemoBundle');$bundle=$helper->ask($input,$output,$question);}

The user will be asked "Please enter the name of the bundle". They can type
some name which will be returned by the
ask() method.
If they leave it empty, the default value (AcmeDemoBundle here) is returned.

If you have a predefined set of answers the user can choose from, you
could use a ChoiceQuestion
which makes sure that the user can only enter a valid string
from a predefined list:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

useSymfony\Component\Console\Question\ChoiceQuestion;// ...publicfunctionexecute(InputInterface$input,OutputInterface$output){// ...$helper=$this->getHelper('question');$question=newChoiceQuestion('Please select your favorite color (defaults to red)',array('red','blue','yellow'),0);$question->setErrorMessage('Color %s is invalid.');$color=$helper->ask($input,$output,$question);$output->writeln('You have just selected: '.$color);// ... do something with the color}

The option which should be selected by default is provided with the third
argument of the constructor. The default is null, which means that no
option is the default one.

If the user enters an invalid string, an error message is shown and the user
is asked to provide the answer another time, until they enter a valid string
or reach the maximum number of attempts. The default value for the maximum number
of attempts is null, which means infinite number of attempts. You can define
your own error message using
setErrorMessage().

You can also specify an array of potential answers for a given question. These
will be autocompleted as the user types:

1
2
3
4
5
6
7
8
9
10
11
12

useSymfony\Component\Console\Question\Question;// ...publicfunctionexecute(InputInterface$input,OutputInterface$output){// ...$bundles=array('AcmeDemoBundle','AcmeBlogBundle','AcmeStoreBundle');$question=newQuestion('Please enter the name of a bundle','FooBundle');$question->setAutocompleterValues($bundles);$name=$helper->ask($input,$output,$question);}

When you ask for a hidden response, Symfony will use either a binary, change
stty mode or use another trick to hide the response. If none is available,
it will fallback and allow the response to be visible unless you set this
behavior to false using
setHiddenFallback()
like in the example above. In this case, a RuntimeException
would be thrown.

You can even validate the answer. For instance, in a previous example you asked
for the bundle name. Following the Symfony naming conventions, it should
be suffixed with Bundle. You can validate that by using the
setValidator()
method:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

useSymfony\Component\Console\Question\Question;// ...publicfunctionexecute(InputInterface$input,OutputInterface$output){// ...$question=newQuestion('Please enter the name of the bundle','AcmeDemoBundle');$question->setValidator(function($answer){if('Bundle'!==substr($answer,-6)){thrownew\RuntimeException('The name of the bundle should be suffixed with \'Bundle\'');}return$answer;});$question->setMaxAttempts(2);$name=$helper->ask($input,$output,$question);}

The $validator is a callback which handles the validation. It should
throw an exception if there is something wrong. The exception message is displayed
in the console, so it is a good practice to put some useful information in it. The
callback function should also return the value of the user's input if the validation
was successful.

You can set the max number of times to ask with the
setMaxAttempts() method.
If you reach this max number it will use the default value. Using null means
the amount of attempts is infinite. The user will be asked as long as they provide an
invalid answer and will only be able to proceed if their input is valid.

useSymfony\Component\Console\Helper\QuestionHelper;useSymfony\Component\Console\Helper\HelperSet;useSymfony\Component\Console\Tester\CommandTester;// ...publicfunctiontestExecute(){// ...$commandTester=newCommandTester($command);$helper=$command->getHelper('question');$helper->setInputStream($this->getInputStream("Test\n"));// Equals to a user inputting "Test" and hitting ENTER// If you need to enter a confirmation, "yes\n" will work$commandTester->execute(array('command'=>$command->getName()));// $this->assertRegExp('/.../', $commandTester->getDisplay());}protectedfunctiongetInputStream($input){$stream=fopen('php://memory','r+',false);fputs($stream,$input);rewind($stream);return$stream;}

By setting the input stream of the QuestionHelper, you imitate what the
console would do internally with all user input through the CLI. This way
you can test any user interaction (even complex ones) by passing an appropriate
input stream.