简体   繁体   中英

Variable number of options for symfony/console component

How would one configure symfony/console to accept a dynamic list of options?

That said - the names for the options aren't known on development step so I need an application to accept everything and expose it using the standard $input->getOption .

Any chance it can be done easily (without hacking the component in million places)?

My attempts included extending the ArgvInput and InputDefinition classes but they failed due to various reasons (they are objective and symfony/console component implementation-specific). Briefly: the former requires parsing to be invoked multiple times; the latter - is instantiated in multiple places so I just couldn't find a proper way to inject it.

You can create your own ArgvInput that will allow all options.

For example you can see the slightly modified version of ArgvInput here

I have only modified lines : 178

And comment out the lines: 188-199

Then pass instance of your version ArgvInput instead of default one to

$input = new AcceptAllArgvInput();    
$kernel = new AppKernel($env, $debug);
$application = new Application($kernel);
$application->run($input);

I have accomplished this in the past using the IS_ARRAY option. Would this not work for your instance as well?

->addArgument('routeParams', InputArgument::IS_ARRAY, "Required Placeholders for route");

My use case was a custom URL generator for a special authentication system. I needed a way to generate URLs for testing. Naturally, each route has a different number of required parameters and I wanted to avoid passing the parameters as a CSV string.

Command examples: Usage: myGenerateToken user route [variables1] ... [variablesN]

 php app/console myGenerateToken 1 productHomePage
 php app/console myGenerateToken 1 getProduct 1
 php app/console myGenerateToken 1 getProductFile 1 changelog

The variables were delivered to the command in the "routeParams" as an array

 $params = $input->getArgument('routeParams');
 var_dump($params);

 array(2) {
   [0] =>
   string(1) "1"
   [1] =>
   string(9) "changelog"
 }

I noticed that there is also an "Option" version called InputOption::VALUE_IS_ARRAY , but I did not have success getting it to work. The argument version InputArgument::IS_ARRAY seems to behave as an option anyways, as it does not error if no arguments are specified.

EDIT:

The author's question is seeking "How do i define variable command line options at run time" where my answer is "How do you provide multiple values for a pre-defined option/argument"

Here is how to implement this on PHP 7+ using symfony/console ^3.0:

abstract class CommandWithDynamicOptions extends Command {

    /** @var array The list of dynamic options passed to the command */
    protected $dynamicOptions = [];

  /**
   * @inheritdoc
   */
  protected function configure() {
    $this->setName('custom:command');

    $this->setDefinition(new class($this->getDefinition(), $this->dynamicOptions) extends InputDefinition {
      protected $dynamicOptions = [];

      public function __construct(InputDefinition $definition, array &$dynamicOptions) {
        parent::__construct();
        $this->setArguments($definition->getArguments());
        $this->setOptions($definition->getOptions());
        $this->dynamicOptions =& $dynamicOptions;
      }

      public function getOption($name) {
        if (!parent::hasOption($name)) {
          $this->addOption(new InputOption($name, null, InputOption::VALUE_OPTIONAL));
          $this->dynamicOptions[] = $name;
        }
        return parent::getOption($name);
      }

      public function hasOption($name) {
        return TRUE;
      }

    });
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM