Skip to content

Console commands: named optional parameters not accepting empty values #19884

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
mstaples opened this issue Sep 8, 2016 · 2 comments
Closed

Comments

@mstaples
Copy link

mstaples commented Sep 8, 2016

When using a console command, if you name an optional parameter and give it an empty value, that value is ignored which can cause unexpected and unhelpful errors.

This can be used to see what I'm talking about:

(requires symfony/console)

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;

require 'vendor/autoload.php';

$application = new Application();
$application
    ->register('echo')
    ->addOption('prefix', null, InputOption::VALUE_OPTIONAL)
    ->addArgument('value', InputArgument::REQUIRED)
    ->setCode(function ($input, $output) {
        var_dump($input->getOption('prefix'));
        var_dump($input->getArgument('value'));
    });

$application->run();

Using this command you can observe some weird things.
These show the first value as prefix and the second value as value:
php command.php echo --prefix="123" "456"
php command.php echo --prefix= "123" "456"
and even
php command.php echo --prefix= "" ""
will output prefix and value each as empty strings

Note the space after the = in the second two instances. This means that if you've got a function somewhere plugging in values to a command and running it, but --prefix doesn't have a value or is an empty string at that point, you could end up with:
php command.php echo --prefix= 'value'
or
php command.php echo --prefix='' 'value'
which return:

[Symfony\Component\Console\Exception\RuntimeException]
Not enough arguments (missing: "value").

either way you will get an error because it doesn't think you've provided a value for the required parameter 'value' when really you have, because it didn't recognize your lack of value or empty string value for 'prefix'. Since the actual error is for a provided parameter, whereas the parsing issue is actually with another parameter these errors can be particularly tricky to identify and track down.

@mstaples mstaples changed the title Console commands: named optional parameters not accepting empty strings Console commands: named optional parameters not accepting empty values Sep 8, 2016
@jakzal jakzal added the Console label Sep 8, 2016
@chalasr
Copy link
Member

chalasr commented Sep 15, 2016

The way we parse options make us unable to consider the empty value of the option if set with an equal as separator, IMHO this is indeed a bug.

Thank you for the well detailed description, it was easy to confirm.

Status: reviewed

@chalasr
Copy link
Member

chalasr commented Sep 15, 2016

See #19946 for the fix

fabpot added a commit that referenced this issue Sep 17, 2016
…n argv (chalasr)

This PR was merged into the 2.7 branch.

Discussion
----------

[Console] Fix parsing optionnal options with empty value in argv

| Q             | A
| ------------- | ---
| Branch?       | 2.7
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #19884
| License       | MIT

If a command takes an option accepting an optional value, passing an empty value to this option will make it parsed as `null`, e.g:

`bin/console dummy --foo ""` gives `['foo' => null]`.
`bin/console dummy --foo=""` gives `['foo' => null]`.

Problems appear when adding an argument with a required value (let's call it `bar`):

`bin/console dummy --foo "" "bar-val"` gives `['foo' => null, 'bar' => 'bar-val']` which is OK.

But:

`bin/console dummy --foo="" "bar-val"`

>  [RuntimeException]
  Not enough arguments (missing: "bar").

The empty value is never considered, as `$argv` just return `"--foo="` for the option, the current implementation doesn't handle the empty value when using an equal as separator, so the `bar` argument value is considered  as the `foo` one, giving a missing required argument at runtime.

This fixes it by explicitly considering the empty value if there is nothing immediately after the equal sign, so args/options correctly take their respective values.

Commits
-------

8952155 [Console] Fix empty optionnal options with = separator in argv
@fabpot fabpot closed this as completed Sep 17, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants