未定义数组索引的意外行为


Unexpected behaviour with undefined array indexes

谁能给我解释一下为什么会发生这种奇怪的事情?我有一个空$_POST数组,我想在该数组中使用一个变量,该变量可能被定义或不定义(在这种情况下-使用一些默认值)。为此,我有一个函数来避免使用所有这些isset()或empty()检查:

function val(&$varToCheck, $defaultValue = false)
{
    if (isset($varToCheck))
        return $varToCheck;
    return $defaultValue;
}

现在如果我输入:

val($_POST['test']); print_r($_POST['test']);

$_POST数组现在包含一个NULL值键"test"。我假设发生这种情况是因为变量是通过引用传递的,并且以某种方式自动创建了一个数组索引。我怎样才能避免这种行为呢?

是。因为你在你的函数中使用了引用,所以这是可行的。这将创建数组索引。更简短的说明方式:

$array = [];
$foo = &$array['foo'];

数组现在是:

array(1) {
  ["foo"]=>
  &NULL
}

创建了index。这就是引用的工作原理(当创建引用时,您将增加一个refcount)。

和- no:不可能通过自定义用户地功能实现isset()。这是因为PHP中的引用不是指针。不能用引用来维持作用域。

您可以对像

这样的数组使用包装器
function valArray(array &$array, $index, $defaultValue = false)
{
    if(array_key_exists($index, $array) && !isset($array[$index]))
    {
        //note, having index & having it set isn't same
        $array[$index] = $defaultValue;
    }
}

首先检查index是否存在。用法如下:

$array = ['foo'=>null];
valArray($array, 'foo', false);
valArray($array, 'bar', true);
//var_dump($array);

那么在此检查之后,您的数组将不会有额外的索引。但是,这也使用了引用,这是一种棘手的方式,它降低了可读性。我强烈建议使用直接的isset()检查。

这就是引用调用的工作原理。举个例子:

function foo($bar, &$error) { ... }
foo('bar', $error);
echo $error;

这个模式的要点是变量$error将在调用作用域中创建,并将使用错误代码填充,因此您稍后可以访问它们。所以,是的,你的数组键将为你创建,如果它不存在。

你想做的事简直是无稽之谈。

function foo($bar) {
    isset($bar) ...
}

这个函数中的isset检查是完全没有意义的,因为$bar是在函数签名中声明的。变量绝对保证存在。您不能使用此构造来测试是否设置了调用作用域中的某个变量,以及是否通过引用传递。变量存在于函数内,并且完全独立于调用范围内的任何内容。您只是将传递给函数,而不是变量本身。

你必须在调用作用域中的$_POST数组上直接使用isset,你不能把它推迟到另一个作用域中。

唯一的替代方法是分别传递数组和键:

val($_POST, 'test')
function val(array $array, $key) {
    isset($array[$key]) ...
}