Override $ argv for getopt

example.php:

$args = __FILE__.' -vvv'; $argv = explode(' ', $args); $argc = count($argv); $GLOBALS['argv'] = $_SERVER['argv'] = $argv; $GLOBALS['argc'] = $_SERVER['argc'] = $argc; var_export(getopt('v')); 

$ example.php -v

> array ('v' => false);

In the end, getopt does not look for $GLOBALS to get argv . So can I override the argv array?

+6
source share
1 answer

TL DR

No, there is no way to do this. There may be other ways to solve the problem, depending on your goals, but redefinition is not one of them.


Superglobal Work

Structure

To understand why this is so, you need to know that super-globals are not just โ€œvariablesโ€ that you refer to. This means that if you use $argv to de-reference the argument list, this does not mean that you will be accessing some data that is stored in the $argv "variable" . Instead, you will access the data container via a link called $argv . However, there are different ways to access this data - well, at least $_SERVER['argv'] or $GLOBALS . To illustrate this, I will go over with the code.

 var_dump($argv, $_SERVER['argv']); unset($argv); var_dump($argv, $_SERVER['argv']); 

This will result in something like:

  array (2) {
   [0] =>
   string (11) "example.php"
   [1] =>
   string (4) "-vvv"
 } // <--------------------- derived from $ argv
 array (2) {
   [0] =>
   string (11) "example.php"
   [1] =>
   string (4) "-vvv"
 } // <--------------------- derived from $ _SERVER ['argv']
 NULL // <------------------ we've unset $ argv, so unset a reference
 array (2) {
   [0] =>
   string (11) "example.php"
   [1] =>
   string (4) "-vvv"
 } // <--------------------- but data is still there and available via another reference

Inside

As you can see, the link may be destroyed, but the actual data will remain intact. This will be stored in a table. Many PHP functions access this structure to retrieve data, and getopt() no exception. So, conclude: yes, you can change the link (or even destroy it), but the actual data will still be superglobal.


getopt()

Now about this feature. Just take a look at this implementation :

 /* Get argv from the global symbol table. We calculate argc ourselves * in order to be on the safe side, even though it is also available * from the symbol table. */ if (PG(http_globals)[TRACK_VARS_SERVER] && (zend_hash_find(HASH_OF(PG(http_globals)[TRACK_VARS_SERVER]), "argv", sizeof("argv"), (void **) &args) != FAILURE || zend_hash_find(&EG(symbol_table), "argv", sizeof("argv"), (void **) &args) != FAILURE) && Z_TYPE_PP(args) == IS_ARRAY ) { //...omitted } 

It clearly states that he will try to find "argv" in symbol_table (if you want - here is a link to - how it will be done exactly). And this means that it will access the actual data, so redefining it from the outside will have no effect.

As a result, getopt() will work with the data that was collected when the script was run, and that the data will contain the actual parameters, regardless of whether you redefine them in your script.

+11
source

Source: https://habr.com/ru/post/969965/


All Articles