Search code examples
phpcommand-line-interfacegetopt

How to modify the command line arguments before getopt()


PHP's getopt() doesn't allow separating argument and its optional value with a space, one needs to either separate with '=' or not separate:

# test.php uses getopt('a::')
> php test.php -a 3 // incorrect
> php test.php -a=3 // correct
> php test.php -a3 // correct

But on the other hand you can use space to separate argument and its required value (one specified as getopt('a:') ). For the sake of consistency and intuitiveness of using spaces, I'd like to correct the command line before it gets processed by getopt() - I have a regexp that replaces '-abc bc' with '-abc=bc'.

But turns out that modifying $argv has no effect on getopt(). I've done some testing with this script:

# t.php
<?php
var_dump($argv);
$argv = array();
var_dump($argv);
var_dump(getopt('a'));
?>

> php t.php -a

array(2) {
  [0] =>
  string(5) "t.php"
  [1] =>
  string(2) "-a"
}
array(0) {
}
array(1) {
  'a' =>
  bool(false)
}

So, there was proper $argv, I've rewritten it to empty array and still getopt() acted like nothing happened.

Questions:

  1. where getopt() gets its input from?
  2. how do I modify this input before getopt() parses it?

Solution

  • Looking at PHP source code, it seems that argc and argv are retrieved directly from the Zend engine when you call getopt, so changing the globals won't affect its behavior. You can check the source code for getopt here: https://github.com/php/php-src/blob/master/ext/standard/basic_functions.c#L4264.

    Anyway, I'm almost sure you can't change that input.