PHP:将引用插入数组



>我正在尝试在某个点插入数组:

$hi = "test";
$var2 = "next";
$arr = array(&$hi);
$arr[] = &$var2; // this works
array_splice($arr, 1, 0, &$var2); // this doesn't

为什么尝试将其插入带有拼接的数组会失败,而使用第一种方法则不会?

快速而肮脏的答案,但请注意,使用引用调用此函数已被弃用,并且可能会(取决于您的 php 配置)生成警告:

array_splice($arr, 1, 0, array(&$var2));

如何和为什么的答案是:正在发生的事情非常微妙。 当您进行拼接时,由于您已在该位置插入了引用,因此实际上正在重新分配 $var 2。 您可以使用以下代码进行验证:

<?php
  $hi = "test";
  $var2 = "next";
  $arr = array(&$hi);
  $arr[] = &$var2; // this works
  printf("=== var2 before splice:n%sn", var_export($var2, TRUE));
  array_splice($arr, 1, 0, &$var2); // this doesn't
  printf("=== var2 after splice:n%sn", var_export($var2, TRUE));
?>

您将获得以下结果:

=== var2 before splice:
'next'
=== var2 after splice:
array (
  0 => 'next',
)

请注意,在拼接之前,$var 2 是一个字符串,正如您所期望的那样("next")。 但是,在拼接之后,$var 2 已被替换为一个包含一个元素的数组,即字符串"next"。

我认为导致它的原因是文档所说的:"如果替换不是数组,它将被类型转换为一个(即(数组)$parameter)。 所以正在发生的事情是这样的:

  • 您将 &$var 2 作为替换传递到数组中。
  • 在内部,php 正在将 &$var 2 转换为数组(&$var 2)。 它实际上可能正在执行等效于 $param = array($param) 的操作,这意味着 &$var 2 将设置为 array(&$var 2),并且由于它是一个引用而不是 $var 2 的副本,因为它通常是一个 2 的副本,这会影响通常超出调用范围的变量。
  • 现在,它将这个新值 $var 2 移动到结束位置,并在第二个位置插入 $var 2 的副本。

我不确定内部发生的所有魔法,但$var肯定会在拼接期间重新分配。 请注意,如果您使用第三个变量,因为它没有将某些内容分配给已作为引用存在的内容,因此它会按预期工作:

<?php
  $hi = "test";
  $var2 = "next";
  $var3 = "last";
  $arr = array(&$hi);
  $arr[] = &$var2; // this works
  array_splice($arr, 1, 0, &$var3);
  printf("=== arr is nown%sn", var_export($arr, TRUE));
?>

生成结果:

=== arr is now
array (
  0 => 'test',
  1 => 'last',
  2 => 'next',
)

您可能需要将最后一个参数设置为数组,否则根据手册,您将被类型转换为数组。

array_splice( $arr, 1, 0, array( &$var2 ) ); 

当我尝试像您这样的示例时,我收到一条警告,指出"调用时间按引用传递已被弃用"。根据这个答案:

您可以在 php.ini 文件中将allow_call_time_pass_reference设置为 true。但这是一个黑客。

在这里,我迭代一个数组($values_arr)并将每个变量的引用存储在另一个数组($params)中。您可以根据需要更改用法。

$params = array();
$values_arr = array('a', 'b', 123);
foreach ($values_arr as $key=>&$val) {
    $params[$key] = &$val;
}

结果

array (size=3)
  0 => &string 'a' (length=1)
  1 => &string 'b' (length=1)
  2 => &int 123

最新更新