-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Console] Option with optional argument always returning null whether specified or not #11572
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
Comments
You can pass the default value as the fifth argument ( |
I did give that a try, but then the default always seems to be present, even if the switch isn't provided. To illustrate: <?php
->addOption(
'createfile',
null,
InputOption::VALUE_OPTIONAL,
'Do not delete the file, specify argument to choose an alternative filename',
true // so we can check $retval === true to differentiate between it being present with no value, or just not present
) php app/console my:command --createfile # results in a getOption retval of true
php app/console my:command # also results in a getOption retval of true So I gave that a spin but still couldn't use it to tell the difference between the option being present with no value or not being present at all. |
there is indeed currently no different between the option being not passed, being passed with no value or being passed with the same value than the default (in case the default is a string as only strings can be passed) Changing |
@stof Thanks for the feedback! Does that make this a documentation bug, or am I misunderstanding? http://symfony.com/doc/current/components/console/introduction.html#using-command-options "It is also possible to make an option optionally accept a value (so that --yell or --yell=loud work). Options can also be configured to accept an array of values." It seems that this feature (optional args for switches) actually serves no purpose if you can't differentiate? Sorry if I'm missing the point! |
@EdwardIII I agree, it doesn't seem to be possible as intended by the documentation. If we can't find a backward compatible way to fix this, we should at least be more clear in the documentation. Do you like to open an issue over there? |
Hey Guys, I ran into this exact same problem. So I forked symfony's/console, and tried to build a solution. Would you guys like to have a look at my tiny try of making console more awesome? It is a proof of concept, I'm not saying this should be made into a PR yet. I just want to share my thoughts and possible implementation of how we could get this to work. Yes the current name of the constant is a silly pun... A couple of notes:
Let's say --dev
And finally the code: |
@ocke Please open a PR. It is much easier to review the code |
workaroundcommand definition:
in the execute method
console
code example:
|
Yeah, this is really overhead to check such options...
Is there any simpler way?.. |
@andkirby You might want to use an array for the call. /**
* Check if empty password option passed
*
* @param \Symfony\Component\Console\Input\InputInterface $input
* @return bool
*/
protected function hasEmptyPasswordOption(InputInterface $input)
{
return null === $input->getOption('password')
&& ($input->hasParameterOption(['-p', '--password']));
} (Edit) |
@dguh
8000
l, yeah, I didn't know the method |
hasParameterOption is the key that makes this usable, for years I believed the InputOption::VALUE_OPTIONAL part of console was broken, in favour of "BC". It is not mentioned on https://symfony.com/doc/current/console/input.html, while "there is no way you can distinguish when the option was used without a value" is. |
…empty) should remain empty (chalasr) This PR was merged into the 3.3-dev branch. Discussion ---------- [Console] Explicitly passed options without value (or empty) should remain empty | Q | A | ------------- | --- | Branch? | master | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #21215 #11572 #12773 | License | MIT | Doc PR | n/a (maybe look at updating the existing one) This conserves empty values for options instead of returning their default values. Code: ```php // cli.php $application = new Application(); $application ->register('echo') ->addOption('prefix', null, InputOption::VALUE_OPTIONAL, null, 'my-default') ->addArgument('value', InputArgument::REQUIRED) ->setCode(function ($input, $output) { var_dump($input->getOption('prefix')); }); $application->run(); ``` Before:  After:  Commits ------- 8086742 [Console] Explicitly passed options without value (or empty) should remain empty
This PR was merged into the 2.2 branch. Discussion ---------- FixCommand - fix diff optional value handling regression fix for #2554: ```php new InputOption('diff', '', InputOption::VALUE_OPTIONAL, 'Also produce diff for each file.', 'sbd'), ``` that means: - 'diff' option may or may not be passed - when it's passed, value for it is optional - 'sbd' is default value of `diff` option regardless it is passed or not (!!!) I guess assumption during creating 2254 was that `sbd` would be only a value for `diff` if one would pass `--diff` (without value). Apparently, it is a value even if one would not pass that option at all, leading to generate diff even without using `--diff` option. ref symfony/symfony#11572 Commits ------- 5546893 FixCommand - fix diff optional value handling
The InputOption::VALUE_OPTIONAL option mode will always return null if you don't set a default value, but returning any other value makes it impossible to correctly determine whether the flag was set or not. Solution is to rely on $input->hasParameterOption() instead. See: https://github.com/symfony/symfony/issues/11572\#issuecomment-197929086
…roblem (Jean85, javiereguiluz) This PR was submitted for the 2.7 branch but it was merged into the 2.8 branch instead (closes #9560). Discussion ---------- Add 2 solutions for the 'option with optional argument' problem While working on facile-it/paraunit#121, I discovered a tricky case with the Console component: using an option with an optional argument seemed impossible! The doc said: > 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. This is NOT TRUE. I've found two possible solutions to this issue (one myself, one in symfony/symfony#11572 (comment)) and this PR introduces them in the docs. I've also moved around the two tips/cautions which were at the end of the article, because with my reword it seemed nicer to me. Commits ------- d3f254d Minor simplifications 1aad365 Minor reword 99f9e3f Simplify the explanation leaving just one solution a05b002 Add 2 solutions for the 'option with optional argument' problem
…roblem (Jean85, javiereguiluz) This PR was submitted for the 2.7 branch but it was merged into the 2.8 branch instead (closes #9560). Discussion ---------- Add 2 solutions for the 'option with optional argument' problem While working on facile-it/paraunit#121, I discovered a tricky case with the Console component: using an option with an optional argument seemed impossible! The doc said: > 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. This is NOT TRUE. I've found two possible solutions to this issue (one myself, one in symfony/symfony#11572 (comment)) and this PR introduces them in the docs. I've also moved around the two tips/cautions which were at the end of the article, because with my reword it seemed nicer to me. Commits ------- 7be002b Add 2 solutions for the 'option with optional argument' problem
I've written an more resuable function that can answer the question for any option
|
From the docs (http://symfony.com/doc/current/components/console/introduction.html#using-command-options):
In practice it doesn't seem to work this way. When creating a Command like this:
And calling it like this:
The value of $createfile is null, even though the switch is present.
I can't find any way to identify that the command is present unless it has a value.
i.e.
php app/console my:command --createfile='/tmp/somefile.txt'
does what you'd expect and returns the string "/tmp/somefile.txt".I can see no other way of identifying whether this option is present?
There seems to be some code supporting the idea that you get a different return value if the option is provided but with no optional value present:
https://github.com/symfony/symfony/blob/2.5/src/Symfony/Component/Console/Input/ArgvInput.php#L234
This looks like it should provide you with an empty string if this parameter is provided but has no value, however in my tests count($this->parsed) was 0, which meant that this inner block could never get executed.
I checked out the unit tests for ArgvInput but couldn't find a test that seemed to be based on this particular use case:
https://github.com/symfony/symfony/blob/2.5/src/Symfony/Component/Console/Tests/Input/ArgvInputTest.php
Symfony version 2.5.2 - app/dev/debug
The text was updated successfully, but these errors were encountered: