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] => )