PHP:检查对象/数组是否为引用

PHP:检查对象/数组是否为引用,php,arrays,reference,pass-by-reference,Php,Arrays,Reference,Pass By Reference,很抱歉,现在很晚了,我想不出办法。。。有人能帮忙吗 $users = array( array( "name" => "John", "age" => "20" ), array( "name" => "Betty", "age" => "22" ) ); $room = array( "furniture" => array("table","bed"

很抱歉,现在很晚了,我想不出办法。。。有人能帮忙吗

$users = array(
    array(
        "name" => "John",
        "age"   => "20"
    ),
    array(
        "name" => "Betty",
        "age"   => "22"
    )
);

$room = array(
    "furniture" => array("table","bed","chair"),
    "objects"   => array("tv","radio","book","lamp"),
    "users" => &$users
);
var_dump$房间显示:

...
'users' => &
...
这意味着“用户”是一个参考

我想这样做:

foreach($room as $key => $val) {
    if(is_reference($val)) unset($room[$key]);
}
主要目标是在不使用任何引用的情况下复制数组

可能吗


谢谢。

您可以在多维数组中测试引用,方法是复制数组,然后依次更改和测试每个条目:

$roomCopy = $room;
foreach ($room as $key => $val) {
  $roomCopy[$key]['_test'] = true;
  if (isset($room[$key]['_test'])) {
    // It's a reference
    unset($room[$key]);
  }
}
unset($roomCopy);

对于示例数据,
$room['furniture']
$roomCopy['furniture']
将是单独的数组(因为
$roomCopy
$room
的副本),因此向其中一个添加新密钥不会影响另一个。但是,
$room['users']
$roomCopy['users']
将引用相同的
$users
数组(因为复制的是引用,而不是数组),因此当我们向
$roomCopy['users']
添加一个键时,它在
$room['users']
中可见

function removeReferences($inbound)
{
    foreach($inbound as $key => $context)
    {
        if(is_array($context))
        {
            $inbound[$key] = removeReferences($context)
        }elseif(is_object($context) && is_reference($context))
        {
            unset($inbound[$key]); //Remove the entity from the array.
        }
    }
    return $inbound;
}

我能管理的最好方法是测试两个变量,以确定其中一个变量是否是对另一个变量的引用:

$x = "something";
$y = &$x;
$z = "something else";

function testReference(&$xVal,&$yVal) {
    $temp = $xVal;
    $xVal = "I am a reference";
    if ($yVal == "I am a reference")  { echo "is reference<br />"; }  else  { echo "is not reference<br />"; }
    $xVal = $temp;
}

testReference($x,$y);
testReference($y,$x);

testReference($x,$z);
testReference($z,$x);

testReference($y,$z);
testReference($z,$y);
要在代码中使用最后一种方法,您需要执行以下操作:

foreach($room as $key => $val) {
    if(isReference($room[$key])) unset($room[$key]);
}
因为$val永远不是引用,因为它是原始数组元素的副本;使用&$val使其始终成为一个引用

function var_reference_count(&$xVal) {
    $ao = is_array($xVal)||is_object($xVal);

    if($ao) { $temp= $xVal;    $xVal=array();    }

    ob_start();        
     debug_zval_dump(&$xVal);
    $dump = ob_get_clean();

    if($ao) $xVal=$temp;

    preg_match('/refcount\((\d*)\)/',$dump,$matches);
    return $matches[1] - 3;
}
//-------------------------------------------------------------------------------------------

这适用于HUDGE对象和阵列

如果要删除递归元素:

<?php
$arr=(object)(NULL); $arr->a=3; $arr->b=&$arr;
//$arr=array('a'=>3, 'b'=>&$arr);
print_r($arr);

$arr_clean=eval('return '.strtr(var_export($arr, true), array('stdClass::__set_state'=>'(object)')).';');
print_r($arr_clean);
?>

第一条评论显示了如何实现:您希望$room不带用户密钥,对吗?有其他的参考资料吗,还是只有用户?是的。问题是我有一个很大的数组,里面有很多交叉引用。我想得到它的一部分,但没有参考资料。因此,简而言之,键可能是可变的。我现在有点懒,我不想追踪所有当前和未来的参考资料。顺便说一句。。我将尝试pritaeas发布的示例…数组中更深层次的引用如何,是否需要剔除这些引用?除了
is\u reference
不存在之外。这就是他想要的;)是的,我不好,我发布了这个帖子,并意识到at试图找到一个解决方案,但克里斯·史密斯的肮脏方法似乎是唯一一种肮脏的解决方案,但富有创造性+1分析pritaeas给出的链接,结果与此解决方案几乎相同,但更加扩展(我仍然喜欢这种简化的编译)。对于简单的值(字符串、int等),您的第一个方法可以工作(因为它基本上是Chris发布的),但不适用于数组。第二种方法很有趣,使用debug_zval_dump“refcount”。但是IMHO它几乎与从var_dump结果中解析出“&”是一样的,不同的是,使用这种方法可以获得引用的数量。顺便说一句,不推荐将引用作为参数传递到函数中。它应该是:debug_zval_dump($xVal);debug_zval_dump()在按引用传递/按值传递方面相当奇怪,文档中专门针对该主题有一整块。但是,除非使用不推荐使用的pass by reference形式,否则debug_zval_dump()似乎在副本(refcount为1)上工作,而不是在变量本身上工作。。。这就像一个被遗忘的痕迹,旧的方法,通过参考传递
<?php
$arr=(object)(NULL); $arr->a=3; $arr->b=&$arr;
//$arr=array('a'=>3, 'b'=>&$arr);
print_r($arr);

$arr_clean=eval('return '.strtr(var_export($arr, true), array('stdClass::__set_state'=>'(object)')).';');
print_r($arr_clean);
?>
stdClass Object ( [a] => 3 [b] => stdClass Object *RECURSION* ) 
stdClass Object ( [a] => 3 [b] => )