
Question:
Sorry to ask, its late and I can't figure a way to do it... anyone can help?
$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 $room shows:
... 'users' => & ...
Which means "users" is a reference.
I would like to do something like this:
foreach($room as $key => $val) { if(is_reference($val)) unset($room[$key]); }
The main goal is to copy the array WITHOUT any references.
Is that possible?
Thank you.
Solution:1
You can test for references in a multi-dimensional array by making a copy of the array, and then altering and testing each entry in turn:
$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);
With your example data, $room['furniture']
and $roomCopy['furniture']
will be separate arrays (as $roomCopy
is a copy of $room
), so adding a new key to one won't affect the other. But, $room['users']
and $roomCopy['users']
will be references to the same $users
array (as it's the reference that's copied, not the array), so when we add a key to $roomCopy['users']
it is visible in $room['users']
.
Solution:2
The best I can manage is a test of two variables to determine if one is a reference to the other:
$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);
but I doubt if it's much help
Really dirty method (not well tested either):
$x = "something"; $y = &$x; $z = "something else"; function isReference(&$xVal) { ob_start(); debug_zval_dump(&$xVal); $dump = ob_get_clean(); preg_match('/refcount\((\d*)\)/',$dump,$matches); if ($matches[1] > 4) { return true; } else { return false; } } var_dump(isReference($x)); var_dump(isReference($y)); var_dump(isReference($z));
To use this last method in your code, you'd need to do something like:
foreach($room as $key => $val) { if(isReference($room[$key])) unset($room[$key]); }
because $val is never a reference as it's a copy of the original array element; and using &$val makes it always a reference
Solution:3
something recursive maybe.
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; }
Solution:4
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; } //-------------------------------------------------------------------------------------------
This works with HUDGE objects and arrays.
Solution:5
if you want to get rid of recursive elements:
<?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); ?>
output:
stdClass Object ( [a] => 3 [b] => stdClass Object *RECURSION* ) stdClass Object ( [a] => 3 [b] => )
Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
EmoticonEmoticon