Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to identify if an option was supplied without a value with Symfony Console?

With the Symfony3 Console, how can I tell when a user supplied an option, but supplied it without a value? As opposed to not supplying the option at all?

As an example, take the following console configuration.

<?php

class MyCommand extends \Symfony\Component\Console\Command\Command
{
    // ...

    protected function configure()
    {
        $this->setName('test')
            ->setDescription('update an existing operation.')
            ->addOption(
                'option',
                null,
                InputOption::VALUE_OPTIONAL,
                'The ID of the operation to update.'
            );
    }
}

The command help will illustrate the option as --option[=OPTION], so I can call this the following ways.

bin/console test
bin/console test --option
bin/console test --option=foo

However, $input->getOption() will return NULL in the first two cases. I expected in the second case that it would return TRUE, or something to indicate the option was supplied.

So I don't know how to identify the difference the option not being supplied at all, and it being supplied but without a value.

If there is no way to tell the difference, what is the use-case for InputOption::VALUE_OPTIONAL?

like image 452
Courtney Miles Avatar asked Sep 09 '16 08:09

Courtney Miles


3 Answers

You're combining two things together. Option with no value InputOption::VALUE_NONE and an option with an optional value InputOption::VALUE_OPTIONAL.

The documentation says: http://symfony.com/doc/current/console/input.html

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 describes exactly your case.

You can't distinguish when a parameter wasn't passed at all or was passed but with no value. That's what InputOption::VALUE_NONE was made for.

Depending on your usecase you can supply a default value for a parameter which will be used in console test and console test --option cases.

Also note, that addOption takes as an argument a shortcut as the second argument.

public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
like image 161
martin Avatar answered Oct 23 '22 18:10

martin


Since Symfony 3.4, you can just set the default to false and check:

  1. if the value is false the option doesn't exist
  2. if the value is null the option exists without a value
  3. otherwise it has its value

e.g.

$this->addOption('force', null, InputOption::VALUE_OPTIONAL, 'Force something', false);

$force = $input->getOption('force') !== false;
like image 13
ScorpioT1000 Avatar answered Oct 23 '22 18:10

ScorpioT1000


Edit on 6/10/21: This only applies to Symfony 3.3 and below. The correct answer is now the one provided by ScorpioT1000

After poking around in Symfony\Component\Console\Input\InputInterface, I discovered the getParameterOption() method which provides the ability to differentiate between an option not used, an option used without a value, and an option used with a value.

In the command's configure() method:

$this->addOption('test', null, InputOption::VALUE_OPTIONAL);

In the command's execute() method:

$test = $input->getOption('test'); $rawTest = $input->getParameterOption('--test');

Produces the following values for the given command lines:

> bin/console some:cmd

$test => null

$rawTest => false

> bin/console some:cmd --test

$test => null

$rawTest => null

> bin/console some:cmd --test=something

$test => "something"

$rawTest => "something"

like image 7
JasonGabler Avatar answered Oct 23 '22 16:10

JasonGabler