在PHP中创建奇怪的数组?

在PHP中创建奇怪的数组?,php,arrays,variables,scope,php-5.3,mysqli,Php,Arrays,Variables,Scope,Php 5.3,Mysqli,我正在阅读mysqli_stmt_bind_的结果,并在以下文件中看到了此代码: 鉴于该行之前既不存在$params,也不存在$row,那么该行为什么/如何工作?来自第一条注释 $variables = array(); $data = array(); $meta = $result->result_metadata(); while($field = $meta->fetch_field()) $variables[] = &am

我正在阅读mysqli_stmt_bind_的结果,并在以下文件中看到了此代码:


鉴于该行之前既不存在$params,也不存在$row,那么该行为什么/如何工作?

来自第一条注释

    $variables = array();
    $data = array();
    $meta = $result->result_metadata();

    while($field = $meta->fetch_field())
        $variables[] = &$data[$field->name]; // pass by reference

    call_user_func_array(array($result, 'bind_result'), $variables);

那么问题出在哪里呢?

它不起作用,因为正如你所说,这些变量不存在

PHP实际上没有变量声明。这意味着在某些情况下,您可以引用变量,而无需事先声明它们。我说有些情况是因为:

foreach($undefinedArray as $key=>$value){
    // will give a notice and a warning
    // notice: undefined variable
    // warning: invalid argument to foreach
}
但这并不意味着你不能这样做:

for($i=0;$i<5;$i++){
    $undefinedArray[]=$i;
}
// will create an array with 5 indexes, each holding the numbers 0 through 4
这就是魔法发生的地方,它实际上是由于&。因为
和$row['unknown_index']
,实际上创建了该索引

这意味着上面的语句做了两件事。首先,它创建一个数组,每个列名保存为
$row
$row[$field->name]
)中的索引。然后它保存一个指向
$params
$row
中每个元素的指针

call_user_func_array(array($stmt, 'bind_result'), $params); 
这将
$stmt->bind_result()
。但是将
$params
中的每个元素作为参数传递给绑定结果。由于它们是通过引用传递的,$行的每个索引将保存每个选定字段

剩下的应该很容易弄清楚了


如果你有任何问题。请随便问 就这样。希望这段代码有意义

附言:作为事后思考,我想澄清我对PHP的一个疑问。如果我尝试填充$results,如下所示:

$results[$index][] = $row;
或者像这样:

$results[] = $row;
$results中的所有键/值对集合重复包含同一集合。希望有人能帮助我们了解PHP的这种行为


谢谢!但是作者为什么要在那里创建两个数组呢?仅仅做$row[$field->name]就足够了吗?(实际上我的意思是(不知道我可以直接链接到注释),但它们是相同的代码…)因为他想使用将数组的每个索引作为参数传递给函数的。通过该函数传递非固定数量的参数更容易,他还需要每个索引都是不会冲突的变量(即
$row
)。这个评论很难解释。如果你仍然不明白,我会重新考虑更新我的帖子:)是的,我明白为什么要使用call_user_func_array()。但是你所说的冲突是什么意思呢?我指的是变量的作用域,仅仅拥有
$row[$field->name]
就可以与同一作用域中的其他变量发生冲突。对不起,我链接到了错误的手册页。链接现在已修复,您看到的评论是错误的。很抱歉,我一开始没有链接到它。在注释中,我的意思是$data在循环中调用之前不存在。
$stmt = $conn->prepare ("SELECT * FROM sample");
$stmt->execute ();
$meta = $stmt->result_metadata();

$params  = array (); // You can skip these lines, PHP initiates arrays on
$row     = array (); // the fly. I prefer doing as much of these initializations
$results = array (); // as possible, on my own.

while ($field = $meta->fetch_field())
{
    /* Again, you can skip the following line, PHP will automatically create
     * a new key/value pair and since we are using the same name for the
     * container of that key/value pair, PHP will actually keep appending. 
     * So after N loops you have an array that contains N key/value pairs
     */
    $row [$field->name] = 0;

    $params[] =& $row[$field->name];
}

/* So now, $params is an array of N references, where reference i points to 
 * the value part of i-th key/val pair in $row 
 */

call_user_func_array (array ($stmt, 'bind_result'), $params);
$index = 0;
while ($stmt->fetch ())
{
    // again, one can skip this. PHP creates this on the fly.
    $results[$index] = array();
    foreach ($row as $key => $val)
    {
        // skip making that temp array!
        $results[$index][$key] = $val;
    }

    $index += 1;
}

return $results;
$results[$index][] = $row;
$results[] = $row;