PHP:在数组中插入引用?

PHP:在数组中插入引用?,php,reference,Php,Reference,我试图在某个点插入数组: $hi = "test"; $var2 = "next"; $arr = array(&$hi); $arr[] = &$var2; // this works array_splice($arr, 1, 0, &$var2); // this doesn't 为什么尝试使用splice将其插入数组失败,而使用第一个方法却没有成功?您可能需要将最后一个参数设置为数组,否则根据设置,您将被类型转换为1 array_splice( $arr, 1,

我试图在某个点插入数组:

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

为什么尝试使用splice将其插入数组失败,而使用第一个方法却没有成功?

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

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

当我尝试像您这样的示例时,会收到一条警告,上面写着“通过引用传递呼叫时间已被弃用”。根据:

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


快速而肮脏的回答,但请注意,使用引用调用此函数是不推荐的,并且可能(取决于您的php配置)生成警告:

array_splice($arr, 1, 0, array(&$var2));
“如何”和“为什么”的答案是:发生的事情相当微妙。进行拼接时,由于已将引用插入该位置,$var2实际上正在重新分配。您可以使用以下代码进行验证:

<?php
  $hi = "test";
  $var2 = "next";
  $arr = array(&$hi);
  $arr[] = &$var2; // this works
  printf("=== var2 before splice:\n%s\n", var_export($var2, TRUE));
  array_splice($arr, 1, 0, &$var2); // this doesn't
  printf("=== var2 after splice:\n%s\n", var_export($var2, TRUE));
?>
请注意,在拼接之前,$var2是一个字符串,正如您所期望的('next')。但是,在拼接之后,$var2已被替换为包含一个元素的数组,即字符串“next”

我认为造成这种情况的原因是文档中所说的:“如果替换不是数组,它将被类型转换为一个(即(数组)$参数)。”所以发生的情况是:

  • 您正在将&$var2作为替换项传递到数组中
  • 在内部,php正在将&$var2转换为数组(&$var2)。它实际上可能在做一些与$param=array($param)等价的事情,这意味着&$var2将被设置为array(&$var2),并且由于它是一个引用,而不是$var2的一个副本,这会影响通常超出调用范围的变量
  • 现在,它将$var2的新值移动到结束位置,并在第二个位置插入$var2的副本
我不确定内部发生了什么,但$var肯定是在拼接过程中被重新分配的。请注意,如果使用第三个变量,因为它没有将某个变量指定给已经作为引用存在的某个变量,所以它会按预期工作:

<?php
  $hi = "test";
  $var2 = "next";
  $var3 = "last";
  $arr = array(&$hi);
  $arr[] = &$var2; // this works
  array_splice($arr, 1, 0, &$var3);
  printf("=== arr is now\n%s\n", var_export($arr, 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

解决方案是正确的,但出于@Travesty3的原因。类型转换不是问题-失败的是调用时间传递引用。根据手册:
如果替换只是一个元素,则无需在其周围放置数组(),除非该元素本身是数组、对象或NULL。
P.s.我认为使用数组(&$var2)调用它的原因是因为在内部,splice不必像通过自赋值一样将&$var2转换为数组(&$var2),从而在过程中更改$var2。您正在显式创建一个新的符号数组(&$var2),该数组在内存中物理上是独立的,不需要自赋值。这种意外的副作用正是不推荐按引用传递调用时间的原因。;)@AndyLobel你应该把被接受的答案改成这个。@Hamish这个答案确实解释了这个问题,但我不认为他真的提到了如何解决这个问题lol(如果我错了,请纠正我)你没有问如何解决它,你问,“为什么尝试用拼接将它插入阵列失败,而使用第一种方法没有?”最“正确”答案是你真的不应该一开始就这么做;正如其他地方提到的,按引用传递调用时间已被弃用。你回答问题的方式(“为什么?”而不是“我怎么做?”),我假设你想知道是什么机制导致了你看到的结果,这是我回答的基础。
$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