Tutorial :PHP: check if object/array is a reference



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
Previous
Next Post »