Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/249.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
php取消设置影响全局范围的本地引用_Php - Fatal编程技术网

php取消设置影响全局范围的本地引用

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行为(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_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;
}