Skip to content
  • About
    • What is Symfony?
    • Community
    • News
    • Contributing
    • Support
  • Documentation
    • Symfony Docs
    • Symfony Book
    • Screencasts
    • Symfony Bundles
    • Symfony Cloud
    • Training
  • Services
    • SensioLabs Professional services to help you with Symfony
    • Platform.sh for Symfony Best platform to deploy Symfony apps
    • SymfonyInsight Automatic quality checks for your apps
    • Symfony Certification Prove your knowledge and boost your career
    • Blackfire Profile and monitor performance of your apps
  • Other
  • Blog
  • Download
sponsored by SensioLabs
  1. Home
  2. Documentation
  3. Components
  4. Console
  5. Helpers
  6. Question Helper
  • Documentation
  • Book
  • Reference
  • Bundles
  • Cloud

Table of Contents

  • Asking the User for Confirmation
  • Asking the User for Information
    • Let the User Choose from a List of Answers
    • Autocompletion
    • Hiding the User's Response
  • Validating the Answer
    • Validating a Hidden Response
  • Testing a Command that Expects Input

Question Helper

Edit this page

Warning: You are browsing the documentation for Symfony 2.6, which is no longer maintained.

Read the updated version of this page for Symfony 6.2 (the current stable version).

Question Helper

2.5

The Question Helper was introduced in Symfony 2.5.

The QuestionHelper provides functions to ask the user for more information. It is included in the default helper set, which you can get by calling getHelperSet():

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

The Question Helper has a single method ask() that needs an InputInterface instance as the first argument, an OutputInterface instance as the second argument and a Question as last argument.

Asking the User for Confirmation

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
use Symfony\Component\Console\Question\ConfirmationQuestion;
// ...

$helper = $this->getHelper('question');
$question = new ConfirmationQuestion('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.

Asking the User for Information

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
use Symfony\Component\Console\Question\Question;
// ...

$question = new Question('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.

Let the User Choose from a List of Answers

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
use Symfony\Component\Console\Question\ChoiceQuestion;
// ...

$helper = $this->getHelper('question');
$question = new ChoiceQuestion(
    '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().

Multiple Choices

Sometimes, multiple answers can be given. The ChoiceQuestion provides this feature using comma separated values. This is disabled by default, to enable this use setMultiselect():

1
2
3
4
5
6
7
8
9
10
11
12
13
use Symfony\Component\Console\Question\ChoiceQuestion;
// ...

$helper = $this->getHelper('question');
$question = new ChoiceQuestion(
    'Please select your favorite colors (defaults to red and blue)',
    array('red', 'blue', 'yellow'),
    '0,1'
);
$question->setMultiselect(true);

$colors = $helper->ask($input, $output, $question);
$output->writeln('You have just selected: ' . implode(', ', $colors));

Now, when the user enters 1,2, the result will be: You have just selected: blue, yellow.

If the user does not enter anything, the result will be: You have just selected: red, blue.

Autocompletion

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
use Symfony\Component\Console\Question\Question;
// ...

$bundles = array('AcmeDemoBundle', 'AcmeBlogBundle', 'AcmeStoreBundle');
$question = new Question('Please enter the name of a bundle', 'FooBundle');
$question->setAutocompleterValues($bundles);

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

Hiding the User's Response

You can also ask a question and hide the response. This is particularly convenient for passwords:

1
2
3
4
5
6
7
8
use Symfony\Component\Console\Question\Question;
// ...

$question = new Question('What is the database password?');
$question->setHidden(true);
$question->setHiddenFallback(false);

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

Caution

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.

Validating the Answer

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
use Symfony\Component\Console\Question\Question;
// ...

$question = new Question('Please enter the name of the bundle', 'AcmeDemoBundle');
$question->setValidator(function ($answer) {
    if ('Bundle' !== substr($answer, -6)) {
        throw new \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.

Validating a Hidden Response

You can also use a validator with a hidden question:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
use Symfony\Component\Console\Question\Question;
// ...

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

$question = new Question('Please enter your password');
$question->setValidator(function ($value) {
    if (trim($value) == '') {
        throw new \Exception('The password can not be empty');
    }

    return $value;
});
$question->setHidden(true);
$question->setMaxAttempts(20);

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

Testing a Command that Expects Input

If you want to write a unit test for a command which expects some kind of input from the command line, you need to set the helper input stream:

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 Symfony\Component\Console\Helper\QuestionHelper;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Tester\CommandTester;

// ...
public function testExecute()
{
    // ...
    $commandTester = new CommandTester($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());
}

protected function getInputStream($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.

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.
TOC
    Version
    We stand with Ukraine.
    Version:
    Symfony Code Performance Profiling

    Symfony Code Performance Profiling

    Be trained by SensioLabs experts (2 to 6 day sessions -- French or English).

    Be trained by SensioLabs experts (2 to 6 day sessions -- French or English).

    Symfony footer

    ↓ Our footer now uses the colors of the Ukrainian flag because Symfony stands with the people of Ukraine.

    Avatar of Al Bunch, a Symfony contributor

    Thanks Al Bunch for being a Symfony contributor

    1 commit • 2 lines changed

    View all contributors that help us make Symfony

    Become a Symfony contributor

    Be an active part of the community and contribute ideas, code and bug fixes. Both experts and newcomers are welcome.

    Learn how to contribute

    Symfony™ is a trademark of Symfony SAS. All rights reserved.

    • What is Symfony?

      • Symfony at a Glance
      • Symfony Components
      • Case Studies
      • Symfony Releases
      • Security Policy
      • Logo & Screenshots
      • Trademark & Licenses
      • symfony1 Legacy
    • Learn Symfony

      • Symfony Docs
      • Symfony Book
      • Reference
      • Bundles
      • Best Practices
      • Training
      • eLearning Platform
      • Certification
    • Screencasts

      • Learn Symfony
      • Learn PHP
      • Learn JavaScript
      • Learn Drupal
      • Learn RESTful APIs
    • Community

      • SymfonyConnect
      • Support
      • How to be Involved
      • Code of Conduct
      • Events & Meetups
      • Projects using Symfony
      • Downloads Stats
      • Contributors
      • Backers
    • Blog

      • Events & Meetups
      • A week of symfony
      • Case studies
      • Cloud
      • Community
      • Conferences
      • Diversity
      • Documentation
      • Living on the edge
      • Releases
      • Security Advisories
      • SymfonyInsight
      • Twig
      • SensioLabs
    • Services

      • SensioLabs services
      • Train developers
      • Manage your project quality
      • Improve your project performance
      • Host Symfony projects

      Deployed on

    Follow Symfony