php取消设置影响全局范围的本地引用
我遇到了一些非常奇怪的php行为(ubuntu 10.04上的5.3.2)。应在本地范围内发生的未设置正在影响调用方函数的范围。下面的代码片段是对我的代码的简化,它显示了我只能假设的bug:php取消设置影响全局范围的本地引用,php,Php,我遇到了一些非常奇怪的php行为(ubuntu 10.04上的5.3.2)。应在本地范围内发生的未设置正在影响调用方函数的范围。下面的代码片段是对我的代码的简化,它显示了我只能假设的bug: <?php function should_not_alter($in) { $in_ref =& $in['level1']; should_only_unset_locally($in); return $in; } function should_only_uns
<?php
function should_not_alter($in)
{
$in_ref =& $in['level1'];
should_only_unset_locally($in);
return $in;
}
function should_only_unset_locally($in)
{
unset($in['level1']['level2_0']);
}
$data = array('level1' => array('level2_0' => 'first value', 'level2_1' => 'second value'));
$data = should_not_alter($data); //test 1
//should_only_unset_locally($data); //test 2
print_r($data);
?>
test1或test2都按预期输出original
。实际上,即使$data
是一个数组,但$in_ref
引用了整个数组(即$in_ref=&$in;
),错误行为也会消失
更新
此行将用返回值不应改变覆盖$data
数组,返回值为$in
。这是正常的行为
另外,当您在['level1']中创建引用时,$in_ref=&$in代码>但是你没有用它做任何事情。它对程序输出没有影响
简短回答:
在调用只应在本地取消设置()函数之前,通过unset($in\u ref)
删除引用变量
长答案:
创建对数组元素的引用时,数组元素将替换为引用。这种行为很奇怪,但它不是一个bug——它是该语言的一个特性,是经过设计的
考虑以下PHP程序:
<?php
$a = array(
'key1' => 'value1',
'key2' => 'value2',
);
$r = &$a['key1'];
$a['key1'] = 'value3';
var_dump($a['key1']);
var_dump($r);
var_dump($a['key1'] === $r);
Output:
string(6) "value3"
string(6) "value3"
bool(true)
该值不存在于$r
或$a['key']
中-这些只是引用。就好像他们都在引用一些可怕的,隐藏的价值。奇怪吧
对于大多数用例来说,这是期望的和有用的行为
现在将此应用于您的程序。下一行修改了
数组中的本地$并用引用替换'level1'
元素:
$in_ref = &$in['level1'];
$in_ref
不是对['level1']
中的$in的引用-相反,它们都引用了相同的怪异值。所以当这条线出现时:
unset($in['level1']['level2_0']);
PHP将['level1']
中的$视为对可疑值的引用,并删除'level2\u 0'
元素。由于它是一个引用,所以在不应改变()函数的范围内也可以感觉到删除
您的特定问题的解决方案是销毁参考变量,该变量将自动将['level1']
中的$恢复到正常行为:
function should_not_alter($in) {
$in_ref =& $in['level1'];
// Do some stuff with $in_ref
// After you're done with it delete the reference to restore $in['level1']
unset($in_ref);
should_only_unset_locally($in);
return $in;
}
是的,看起来像只虫子
正如函数名所暗示的,不应该改变
不应该改变数组,因为数组是按值传递的。(当然,我并不是仅仅基于名称——它也不应该根据其定义改变任何东西。)
事实上,注释$in_ref=&$in['level1']
让它把$in
单独留在里面,这似乎进一步证明了它是一个bug。这是一个很奇怪的小怪癖。不知道内部会发生什么导致这种情况
我会在PHP bug跟踪器上提交一份bug报告。不管它值多少钱,它仍然存在于5.4.6中。$in_ref=&$in['level1'代码>当然有效果。如果您将其注释掉,那么在测试1或测试2期间,“第一个值”不会在全局范围内未设置。您是对的。但是,只有当$data
被分配到时,全局范围才会生效。您是否有一些来源可以确认它确实符合设计,并且这不是一个bug?+1到@eis。我怀疑真正发生的是PHP“哦,糟了,那很难修复。我们可以……把它称为一个功能吗?”对发生的事情的解释并不能说服我它为什么会发生。“奇怪,嗯?”和“自动”这两个短语的使用对我来说意味着一个bug。我还认为对于大多数用例来说,这是期望的和有用的行为。
因为隐藏的副作用几乎从来都不是期望的行为。但在这一点上,我开始忘乎所以了。@eis也是+1。这种行为似乎与php处理除较低级别数组之外的所有其他引用变量的方式不一致。请注意,即使是数组的顶层(即$in_ref=&$in;
)也不会产生错误行为。这不是错误。这是出于设计,请看我修改后的答案:我看到分配给它的开发人员关闭了它。不过,他似乎没有正确地解释这个问题。我很好奇你是否已经写过或考虑过写一些后续文章?是的,我也看到了。我在历史上看到了你的评论。似乎开发人员不明白我想展示什么。也许他实际上并没有运行我的代码,因为他说注释掉这行代码并没有什么区别,而且很明显是这样的。
$in_ref = &$in['level1'];
unset($in['level1']['level2_0']);
function should_not_alter($in) {
$in_ref =& $in['level1'];
// Do some stuff with $in_ref
// After you're done with it delete the reference to restore $in['level1']
unset($in_ref);
should_only_unset_locally($in);
return $in;
}