为getopt覆盖$ argv

Nem*_*den 7 php

使用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'));
Run Code Online (Sandbox Code Playgroud)

$ example.php -v

> array('v'=> false);

最终getopt不羡慕$GLOBALS得到argv.那么我有什么方法可以覆盖argv数组?

Alm*_* Do 13

TL; DR

不,没有本地方法可以做到这一点.根据您的目标,可能有其他方法可以解决问题,但覆盖不是其中之一.


在超全局上运行

结构体

要知道为什么会这样,你应该知道,超级全局变量不仅仅是你所指的"变量".这意味着,如果您$argv用于取消引用参数列表,则并不意味着您将访问存储在"变量"中的 某些数据$argv.相反,您将通过"链接"访问数据容器,称为$argv.但是,有不同的方法来访问此数据 - $_SERVER['argv']$GLOBALS至少是数组.为了说明,我将使用代码:

var_dump($argv, $_SERVER['argv']);
unset($argv);
var_dump($argv, $_SERVER['argv']);
Run Code Online (Sandbox Code Playgroud)

这将导致类似于:

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
Run Code Online (Sandbox Code Playgroud)

内部

如您所见,可以销毁引用,但实际数据将保持不变.这将存储在符号表中.许多PHP函数正在访问此结构以检索数据,并且getopt()不是例外.所以结论是 - 是的,你可以修改引用(甚至破坏它),但实际数据仍然是超级全局的.


getopt()

现在,关于这个功能.看看它的实现:

/* 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
}
Run Code Online (Sandbox Code Playgroud)

它明确指出,它会尝试搜索"argv"symbol_table(如果你想-这里是一个链接- 如何将准确地完成).这意味着 - 它将访问实际数据,因此,从外部覆盖它将不起作用.

因此 - getopt()无论您是否在脚本中覆盖它们,都将使用在脚本启动时收集的数据,并且该数据将包含实际参数.