|  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #34291 reference comparison: $a isIdenticalTo $b
Submitted: 2005-08-28 23:02 UTC Modified: 2016-03-27 08:44 UTC
Avg. Score:4.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: csaba at alum dot mit dot edu Assigned: krakjoe (profile)
Status: Closed Package: *General Issues
PHP Version: 5.1.0RC1 OS:
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
Block user comment
Status: Assign to:
Bug Type:
From: csaba at alum dot mit dot edu
New email:
PHP Version: OS:


 [2005-08-28 23:02 UTC] csaba at alum dot mit dot edu
I would like to recommend a (boolean) operator:
$ref1 isIdenticalTo $ref2
to compare whether two references are identical.

A main use of this is in tree traversal.  For example:
$a = array(7);
$a[] = &$a;        // we now have a self reference
print $a[1][1][1][0];     // => 7.  All is OK
if ($a==$a[1]) print "same";   // Fails

Both $a==$a[1] and $a===$a[1] will fail because the nesting level is too deep.  This is in agreement with the documentation, which says that values are tested.

If I could do isIdenticalTo however (one could not use ==== with a straight face), then by placing the references of subarrays encountered onto an $aVisited array, I could run through them myself and check with isIdenticalTo and thus avoid exceeding a nesting level.

An example where this (appropriately) happens is with $GLOBALS, since $GLOBALS["GLOBALS"] isIdenticalTo $GLOBALS.

Thanks for considering this,
Csaba Gabor from Vienna


Add a Patch

Pull Requests

Add a Pull Request


AllCommentsChangesGit/SVN commitsRelated reports
 [2005-08-30 20:28 UTC] csaba at alum dot mit dot edu
OK, I was a bit hasty in what I recommended.  In particular, there are two distinct cases:  In one case, we want to know whether two references are the same.  In the second, we'd like to know whether the values of two references are the same.  The latter is the same as === except for arrays.

So, I have written a function, isIdentical to do both of these.  For the case of arrays and ===, I poke a new element onto one array and see if it shows up on the other.  For the reference checking, I take a similar approach, except that one has to be careful with arrays, because any reference pointing to the original array that is poked is destroyed so this has to be fixed up.  That is the reason for the two foreach loops - it detects self references that were destroyed and fixes them.

The whole methodology employed in the example below - see what happens if you poke at it - does not give one the warm fuzzies.  I'd still prefer to see isIdentical implemented as a native PHP function.

function isIdentical(&$ref1, &$ref2, $referencesP=false) {
  // if $referencesP is true, isIdentical returns true
  //     iff $ref1====$ref2.  That is, if
  //     $ref2=somethingElse changes $ref1, to
  //     somethingElse, too (Ie. the same reference)
  // if $referencesP is false, isIdentical is the same
  //     as $ref1===$ref2 for non objects/arrays.
  //     For objects/arrays $ref1===$ref2 iff a change
  //     in (a property of) $ref2 is reflected in $ref1
  //     (ie. the same object/array)
  if (gettype($ref1)!=($type=gettype($ref2))) return false;
  if ($arrayP=($type=="array")) {
    if (count($ref1)!=count($ref2)) return false;
    if (!$referencesP) {// are $ref1,$ref2 the same object
      $test = "isSameObjectTest";
      while (array_key_exists($test, $ref2))
        $test .= rand();
      if (array_key_exists($test, $ref1)) return false;
      $ref2[$test] = 13;
      $result = array_key_exists($test,$ref1);
      unset ($ref2[$test]);
      return $result; }
    $aType = array();
    foreach ($ref2 as $key=>$val)
      $aType[$key] = gettype($val); }
  // accounts for objects, too.  
  elseif (!$referencesP) return $ref1===$ref2;	
  $tmp = $ref2;
  $ref2 = ($type=="string") ? 13 : "fred";
  $result = gettype($ref1)!=$type;
  // now we must repair the damage
  $ref2 = $tmp;
  if ($arrayP)
    foreach ($ref2 as $key=>&$ref)
      if ($aType[$key]!=gettype($ref)) $ref=&$ref2;
  return $result;

Csaba Gabor from Vienna

//for comparison, see

Tested with:
$a = array(7); $a[] = &$b;
$b = array(8); $b[] = &$a;
$c = array(9); $c[] = &$a;
print "<pre>"; 
print "GLOBALS test " . (isIdentical($GLOBALS,
    $GLOBALS["GLOBALS"], true) ? "passed" : "failed");
print "\nDouble test " . (isIdentical($b[1],
    $c[1], true) ? "passed\n" : "failed\n");
$c[2] = "test from c";
$b[3] = "test from b";
$a[4] = "test from a";
var_dump($a); print "\n";
var_dump($b); print "\n";
var_dump($c); print "</pre>";
 [2016-03-27 08:44 UTC]
-Status: Open +Status: Closed -Package: Feature/Change Request +Package: *General Issues -Assigned To: +Assigned To: krakjoe
 [2016-03-27 08:44 UTC]
Sometime between version 5.3 and 5.4, the restriction that caused you to request this feature was lifted.

Sorry about the wait :)
PHP Copyright © 2001-2023 The PHP Group
All rights reserved.
Last updated: Sat Feb 04 12:03:44 2023 UTC