Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 9e129bc

Browse filesBrowse files
committed
feature #3752 [Console] Add documentation for QuestionHelper (romainneutron)
This PR was merged into the master branch. Discussion ---------- [Console] Add documentation for QuestionHelper | Q | A | ------------- | --- | Doc fix? | no | New docs? | yes (symfony/symfony#10606) | Applies to | 2.5+ This is the documentation for the new Question Helper Commits ------- f4ee337 [Console] Add documentation for QuestionHelper
2 parents 552c780 + f4ee337 commit 9e129bc
Copy full SHA for 9e129bc

File tree

Expand file treeCollapse file tree

4 files changed

+274
-0
lines changed
Filter options
Expand file treeCollapse file tree

4 files changed

+274
-0
lines changed

‎components/console/helpers/dialoghelper.rst

Copy file name to clipboardExpand all lines: components/console/helpers/dialoghelper.rst
+9Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44
Dialog Helper
55
=============
66

7+
.. caution::
8+
9+
The Dialog Helper was deprecated in Symfony 2.5 and will be removed in
10+
Symfony 3.0. You should now use the
11+
:doc:`Question Helper </components/console/helpers/questionhelper>` instead,
12+
which is simpler to use.
13+
714
The :class:`Symfony\\Component\\Console\\Helper\\DialogHelper` provides
815
functions to ask the user for more information. It is included in the default
916
helper set, which you can get by calling
@@ -149,6 +156,8 @@ You can also ask and validate a hidden response::
149156
if (trim($value) == '') {
150157
throw new \Exception('The password can not be empty');
151158
}
159+
160+
return $value;
152161
};
153162

154163
$password = $dialog->askHiddenResponseAndValidate(

‎components/console/helpers/index.rst

Copy file name to clipboardExpand all lines: components/console/helpers/index.rst
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ The Console Helpers
1111
formatterhelper
1212
progressbar
1313
progresshelper
14+
questionhelper
1415
table
1516
tablehelper
1617

‎components/console/helpers/map.rst.inc

Copy file name to clipboardExpand all lines: components/console/helpers/map.rst.inc
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
* :doc:`/components/console/helpers/formatterhelper`
33
* :doc:`/components/console/helpers/progressbar`
44
* :doc:`/components/console/helpers/progresshelper`
5+
* :doc:`/components/console/helpers/questionhelper`
56
* :doc:`/components/console/helpers/table`
67
* :doc:`/components/console/helpers/tablehelper`
+263Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
.. index::
2+
single: Console Helpers; Question Helper
3+
4+
Question Helper
5+
===============
6+
7+
.. versionadded:: 2.5
8+
The Question Helper was introduced in Symfony 2.5.
9+
10+
The :class:`Symfony\\Component\\Console\\Helper\\QuestionHelper` provides
11+
functions to ask the user for more information. It is included in the default
12+
helper set, which you can get by calling
13+
:method:`Symfony\\Component\\Console\\Command\\Command::getHelperSet`::
14+
15+
$helper = $this->getHelperSet()->get('question');
16+
17+
The Question Helper has a single method
18+
:method:`Symfony\\Component\\Console\\Command\\Command::ask` that needs an
19+
:class:`Symfony\\Component\\Console\\Output\\InputInterface` instance as the
20+
first argument, an :class:`Symfony\\Component\\Console\\Output\\OutputInterface`
21+
instance as the second argument and a
22+
:class:`Symfony\\Component\\Console\\Question\\Question` as last argument.
23+
24+
Asking the User for Confirmation
25+
--------------------------------
26+
27+
Suppose you want to confirm an action before actually executing it. Add
28+
the following to your command::
29+
30+
use Symfony\Component\Console\Question\ConfirmationQuestion;
31+
// ...
32+
33+
$helper = $this->getHelperSet()->get('question');
34+
$question = new ConfirmationQuestion('Continue with this action?', false);
35+
36+
if (!$helper->ask($input, $output, $question)) {
37+
return;
38+
}
39+
40+
In this case, the user will be asked "Continue with this action?". If the user
41+
answers with ``y`` it returns ``true`` or ``false`` if they answer with ``n``.
42+
The second argument to
43+
:method:`Symfony\\Component\\Console\\Question\\ConfirmationQuestion::__construct`
44+
is the default value to return if the user doesn't enter any input. Any other
45+
input will ask the same question again.
46+
47+
Asking the User for Information
48+
-------------------------------
49+
50+
You can also ask a question with more than a simple yes/no answer. For instance,
51+
if you want to know a bundle name, you can add this to your command::
52+
53+
use Symfony\Component\Console\Question\Question;
54+
// ...
55+
56+
$question = new Question('Please enter the name of the bundle', 'AcmeDemoBundle');
57+
58+
$bundle = $helper->ask($input, $output, $question);
59+
60+
The user will be asked "Please enter the name of the bundle". They can type
61+
some name which will be returned by the
62+
:method:`Symfony\\Component\\Console\\Helper\\QuestionHelper::ask` method.
63+
If they leave it empty, the default value (``AcmeDemoBundle`` here) is returned.
64+
65+
Let the User Choose from a List of Answers
66+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
67+
68+
If you have a predefined set of answers the user can choose from, you
69+
could use a :class:`Symfony\\Component\\Console\\Question\\ChoiceQuestion`
70+
which makes sure that the user can only enter a valid string
71+
from a predefined list::
72+
73+
use Symfony\Component\Console\Question\ChoiceQuestion;
74+
// ...
75+
76+
$helper = $app->getHelperSet()->get('question');
77+
$question = new ChoiceQuestion(
78+
'Please select your favorite color (defaults to red)',
79+
array('red', 'blue', 'yellow'),
80+
'red'
81+
);
82+
$question->setErrorMessage('Color %s is invalid.');
83+
84+
$color = $helper->ask($input, $output, $question);
85+
$output->writeln('You have just selected: '.$color);
86+
87+
// ... do something with the color
88+
89+
The option which should be selected by default is provided with the third
90+
argument of the constructor. The default is ``null``, which means that no
91+
option is the default one.
92+
93+
If the user enters an invalid string, an error message is shown and the user
94+
is asked to provide the answer another time, until they enter a valid string
95+
or reach the maximum number of attempts. The default value for the maximum number
96+
of attempts is ``null``, which means infinite number attempts. You can define
97+
your own error message using
98+
:method:`Symfony\\Component\\Console\\Question\\ChoiceQuestion::setErrorMessage`.
99+
100+
Multiple Choices
101+
................
102+
103+
Sometimes, multiple answers can be given. The ``ChoiceQuestion`` provides this
104+
feature using comma separated values. This is disabled by default, to enable
105+
this use :method:`Symfony\\Component\\Console\\Question\\ChoiceQuestion::setMultiselect`::
106+
107+
use Symfony\Component\Console\Question\ChoiceQuestion;
108+
// ...
109+
110+
$helper = $app->getHelperSet()->get('question');
111+
$question = new ChoiceQuestion(
112+
'Please select your favorite color (defaults to red)',
113+
array('red', 'blue', 'yellow'),
114+
'red'
115+
);
116+
$question->setMultiselect(true);
117+
118+
$colors = $helper->ask($input, $output, $question);
119+
$output->writeln('You have just selected: ' . implode(', ', $colors));
120+
121+
Now, when the user enters ``1,2``, the result will be:
122+
``You have just selected: blue, yellow``.
123+
124+
Autocompletion
125+
~~~~~~~~~~~~~~
126+
127+
You can also specify an array of potential answers for a given question. These
128+
will be autocompleted as the user types::
129+
130+
use Symfony\Component\Console\Question\Question;
131+
// ...
132+
133+
$bundles = array('AcmeDemoBundle', 'AcmeBlogBundle', 'AcmeStoreBundle');
134+
$question = new Question('Please enter the name of a bundle', 'FooBundle');
135+
$question->setAutocompleterValues($bundles);
136+
137+
$name = $helper->ask($input, $output, $question);
138+
139+
Hiding the User's Response
140+
~~~~~~~~~~~~~~~~~~~~~~~~~~
141+
142+
You can also ask a question and hide the response. This is particularly
143+
convenient for passwords::
144+
145+
use Symfony\Component\Console\Question\Question;
146+
// ...
147+
148+
$question = new Question('What is the database password?');
149+
$question->setHidden(true);
150+
$question->setHiddenFallback(false);
151+
152+
$password = $helper->ask($input, $output, $question);
153+
154+
.. caution::
155+
156+
When you ask for a hidden response, Symfony will use either a binary, change
157+
stty mode or use another trick to hide the response. If none is available,
158+
it will fallback and allow the response to be visible unless you set this
159+
behavior to ``false`` using
160+
:method:`Symfony\\Component\\Console\\Question\\Question::setHiddenFallback`
161+
like in the example above. In this case, a ``RuntimeException``
162+
would be thrown.
163+
164+
Validating the Answer
165+
---------------------
166+
167+
You can even validate the answer. For instance, in a previous example you asked
168+
for the bundle name. Following the Symfony naming conventions, it should
169+
be suffixed with ``Bundle``. You can validate that by using the
170+
:method:`Symfony\\Component\\Console\\Question\\Question::setValidator`
171+
method::
172+
173+
use Symfony\Component\Console\Question\Question;
174+
// ...
175+
176+
$question = new Question('Please enter the name of the bundle', 'AcmeDemoBundle');
177+
$question->setValidator(function ($answer) {
178+
if ('Bundle' !== substr($answer, -6)) {
179+
throw new \RuntimeException(
180+
'The name of the bundle should be suffixed with \'Bundle\''
181+
);
182+
}
183+
return $answer;
184+
});
185+
$question->setMaxAttempts(2);
186+
187+
$name = $helper->ask($input, $output, $question);
188+
189+
The ``$validator`` is a callback which handles the validation. It should
190+
throw an exception if there is something wrong. The exception message is displayed
191+
in the console, so it is a good practice to put some useful information in it. The
192+
callback function should also return the value of the user's input if the validation
193+
was successful.
194+
195+
You can set the max number of times to ask with the
196+
:method:`Symfony\\Component\\Console\\Question\\Question::setMaxAttempts` method.
197+
If you reach this max number it will use the default value. Using ``null`` means
198+
the amount of attempts is infinite. The user will be asked as long as they provide an
199+
invalid answer and will only be able to proceed if their input is valid.
200+
201+
Validating a Hidden Response
202+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
203+
204+
You can also use a validator with a hidden question::
205+
206+
use Symfony\Component\Console\Question\Question;
207+
// ...
208+
209+
$helper = $this->getHelperSet()->get('question');
210+
211+
$question = new Question('Please enter your password');
212+
$question->setValidator(function ($value) {
213+
if (trim($value) == '') {
214+
throw new \Exception('The password can not be empty');
215+
}
216+
217+
return $value;
218+
});
219+
$question->setHidden(true);
220+
$question->setMaxAttempts(20);
221+
222+
$password = $helper->ask($input, $output, $question);
223+
224+
225+
Testing a Command that Expects Input
226+
------------------------------------
227+
228+
If you want to write a unit test for a command which expects some kind of input
229+
from the command line, you need to set the helper input stream::
230+
231+
use Symfony\Component\Console\Helper\QuestionHelper;
232+
use Symfony\Component\Console\Helper\HelperSet;
233+
use Symfony\Component\Console\Tester\CommandTester;
234+
235+
// ...
236+
public function testExecute()
237+
{
238+
// ...
239+
$commandTester = new CommandTester($command);
240+
241+
$helper = $command->getHelper('question');
242+
$helper->setInputStream($this->getInputStream('Test\\n'));
243+
// Equals to a user inputting "Test" and hitting ENTER
244+
// If you need to enter a confirmation, "yes\n" will work
245+
246+
$commandTester->execute(array('command' => $command->getName()));
247+
248+
// $this->assertRegExp('/.../', $commandTester->getDisplay());
249+
}
250+
251+
protected function getInputStream($input)
252+
{
253+
$stream = fopen('php://memory', 'r+', false);
254+
fputs($stream, $input);
255+
rewind($stream);
256+
257+
return $stream;
258+
}
259+
260+
By setting the input stream of the ``QuestionHelper``, you imitate what the
261+
console would do internally with all user input through the cli. This way
262+
you can test any user interaction (even complex ones) by passing an appropriate
263+
input stream.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.