Skip to content

Add 2 solutions for the 'option with optional argument' problem #9560

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 52 additions & 15 deletions console/input.rst
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,15 @@ values after a white space or an ``=`` sign (e.g. ``--iterations 5`` or
``--iterations=5``), but short options can only use white spaces or no
separation at all (e.g. ``-i 5`` or ``-i5``).

.. caution::

While it is possible to separate an option from its value with a white space,
using this form leads to an ambiguity should the option appear before the
command name. For example, ``php app/console --iterations 5 app:greet Fabien``
is ambiguous; Symfony would interpret ``5`` as the command name. To avoid
this situation, always place options after the command name, or avoid using
a space to separate the option name from its value.

There are four option variants you can use:

``InputOption::VALUE_IS_ARRAY``
Expand Down Expand Up @@ -209,25 +218,53 @@ You can combine ``VALUE_IS_ARRAY`` with ``VALUE_REQUIRED`` or
array('blue', 'red')
);

.. tip::
Options with optional arguments
-------------------------------

There is nothing forbidding you to create a command with an option that
optionally accepts a value. However, there is no way you can distinguish
when the option was used without a value (``command --language``) or when
it wasn't used at all (``command``). In both cases, the value retrieved for
the option will be ``null``.
There is nothing forbidding you to create a command with an option that
optionally accepts a value, but it's a bit tricky. Consider this example::

Similarly, due to a PHP limitation, there is no way to pass an empty string
as the value of an option. In ``command --prefix`` and ``command --prefix=''``
cases, the value of the ``prefix`` option will be ``null``.
// ...
use Symfony\Component\Console\Input\InputOption;

$this
// ...
->addOption(
'yell',
null,
InputOption::VALUE_OPTIONAL,
'Should I yell while greeting?'
);

This option can be used in 3 ways: ``--yell``, ``yell=louder``, and not passing
the option at all. However, it's hard to distinguish between passing the option
without a value (``greet --yell``) and not passing the option (``greet``).

To solve this issue, you have to set the option's default value to ``false``::

// ...
use Symfony\Component\Console\Input\InputOption;

$this
// ...
->addOption(
'yell',
null,
InputOption::VALUE_OPTIONAL,
'Should I yell while greeting?',
false // this is the new default value, instead of null
);

Now check the value of the option and keep in mind that ``false !== null``::

$optionValue = $input->getOptions('yell');
$yell = ($optionValue !== false);
$yellLouder = ($optionValue === 'louder');

.. caution::

While it is possible to separate an option from its value with a white space,
using this form leads to an ambiguity should the option appear before the
command name. For example, ``php app/console --iterations 5 app:greet Fabien``
is ambiguous; Symfony would interpret ``5`` as the command name. To avoid
this situation, always place options after the command name, or avoid using
a space to separate the option name from its value.
Due to a PHP limitation, passing an empty string is indistinguishable from
not passing any value at all. In ``command --prefix`` and ``command --prefix=''``
cases, the value of the ``prefix`` option will be ``null``.

.. _`docopt standard`: http://docopt.org/