note 72203 added to language.references.spot
| From: | BenBE at omorphia dot de | Date: | Sun, 07 Jan 2007 19:37:45 +0000 |
| Subject: | note 72203 added to language.references.spot | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-121394@lists.php.net to get a copy of this message | ||
Hi,
If you want to check if two variables are referencing each other (i.e. point to the same memory) you
can use a function like this:
<?php
function same_type(&$var1, &$var2){
return gettype($var1) === gettype($var2);
}
function is_ref(&$var1, &$var2) {
//If a reference exists, the type IS the same
if(!same_type($var1, $var2)) {
return false;
}
$same = false;
//We now only need to ask for var1 to be an array ;-)
if(is_array($var1)) {
//Look for an unused index in $var1
do {
$key = uniqid("is_ref_", true);
} while(array_key_exists($key, $var1));
//The two variables differ in content ... They can't be the same
if(array_key_exists($key, $var2)) {
return false;
}
//The arrays point to the same data if changes are reflected in $var2
$data = uniqid("is_ref_data_", true);
$var1[$key] =& $data;
//There seems to be a modification ...
if(array_key_exists($key, $var2)) {
if($var2[$key] === $data) {
$same = true;
}
}
//Undo our changes ...
unset($var1[$key]);
} elseif(is_object($var1)) {
//The same objects are required to have equal class names ;-)
if(get_class($var1) !== get_class($var2)) {
return false;
}
$obj1 = array_keys(get_object_vars($var1));
$obj2 = array_keys(get_object_vars($var2));
//Look for an unused index in $var1
do {
$key = uniqid("is_ref_", true);
} while(in_array($key, $obj1));
//The two variables differ in content ... They can't be the same
if(in_array($key, $obj2)) {
return false;
}
//The arrays point to the same data if changes are reflected in $var2
$data = uniqid("is_ref_data_", true);
$var1->$key =& $data;
//There seems to be a modification ...
if(isset($var2->$key)) {
if($var2[$key] === $data) {
$same = true;
}
}
//Undo our changes ...
unset($var1->$key);
} elseif (is_resource($var1)) {
if(get_resource_type($var1) !== get_resource_type($var2)) {
return false;
}
return ((string) $var1) === ((string) $var2);
} else {
//Simple variables ...
if($var1!==$var2) {
//Data mismatch ... They can't be the same ...
return false;
}
//To check for a reference of a variable with simple type
//simply store its old value and check against modifications of the second variable ;-)
do {
$key = uniqid("is_ref_", true);
} while($key === $var1);
$tmp = $var1; //WE NEED A COPY HERE!!!
$var1 = $key; //Set var1 to the value of $key (copy)
$same = $var1 === $var2; //Check if $var2 was modified too ...
$var1 = $tmp; //Undo our changes ...
}
return $same;
}
?>
Although this implementation is quite complete, it can't handle function references and some
other minor stuff ATM.
This function is especially useful if you want to serialize a recursive array by hand.
The usage is something like:
<?php
$a = 5;
$b = 5;
var_dump(is_ref($a, $b)); //false
$a = 5;
$b = $a;
var_dump(is_ref($a, $b)); //false
$a = 5;
$b =& $a;
var_dump(is_ref($a, $b)); //true
echo "---\n";
$a = array();
var_dump(is_ref($a, $a)); //true
$a[] =& $a;
var_dump(is_ref($a, $a[0])); // true
echo "---\n";
$b = array(array());
var_dump(is_ref($b, $b)); //true
var_dump(is_ref($b, $b[0])); //false
echo "---\n";
$b = array();
$b[] = $b;
var_dump(is_ref($b, $b)); //true
var_dump(is_ref($b, $b[0])); //false
var_dump(is_ref($b[0], $b[0][0])); //true*
echo "---\n";
var_dump($a);
var_dump($b);
?>
* Please note the internal behaviour of PHP that seems to do the reference assignment BEFORE
actually copying the variable!!! Thus you get an array containing a (different) recursive array for
the last testcase, instead of an array containing an empty array as you could expect.
BenBE.
----
Server IP: 217.160.72.57
Probable Submitter: 217.93.216.166
----
Manual Page -- http://www.php.net/manual/en/language.references.spot.php
Edit -- https://master.php.net/note/edit/72203
Del: integrated -- https://master.php.net/note/delete/72203/integrated
Del: useless -- https://master.php.net/note/delete/72203/useless
Del: bad code -- https://master.php.net/note/delete/72203/bad+code
Del: spam -- https://master.php.net/note/delete/72203/spam
Del: non-english -- https://master.php.net/note/delete/72203/non-english
Del: in docs -- https://master.php.net/note/delete/72203/in+docs
Del: other reasons-- https://master.php.net/note/delete/72203
Reject -- https://master.php.net/note/reject/72203
Search -- https://master.php.net/manage/user-notes.php