PHP
downloads | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

Clases y Objetos (PHP 5)> <Clases y Objetos (PHP 4)
Last updated: Fri, 22 Aug 2008

view this page in

Comparación de objetos

En PHP 4, los objetos son comparados en una forma muy simple: Dos instancias de objeto son iguales si tienen los mismos atributos y valores, y son instancias de la misma clase. Reglas similares se aplican cuando se comparan dos objetos usando el operador de identidad (===).

Si ejecutáramos el código del siguiente ejemplo:

Example #1 Ejemplo de comparación de objetos en PHP 4

<?php
function bool_a_cadena($bool) {
    if (
$bool === false) {
            return 
'FALSE';
    } else {
            return 
'TRUE';
    }
}

function 
compararObjetos(&$o1, &$o2) {
    echo 
'o1 == o2 : '.bool_a_cadena($o1 == $o2)."\n";
    echo 
'o1 != o2 : '.bool_a_cadena($o1 != $o2)."\n";
    echo 
'o1 === o2 : '.bool_a_cadena($o1 === $o2)."\n";
    echo 
'o1 !== o2 : '.bool_a_cadena($o1 !== $o2)."\n";
}

class 
Bandera {
    var 
$bandera;

    function 
Bandera($bandera=true) {
            
$this->bandera $bandera;
    }
}

class 
BanderaCambiante extends Bandera {

    function 
encender() {
        
$this->bandera true;
    }

    function 
apagar() {
        
$this->bandera false;
    }
}

$o = new Bandera();
$p = new Bandera(false);
$q = new Bandera();

$r = new BanderaCambiante();

echo 
"Comparar instancias creadas con los mismos parámetros\n";
compararObjetos($o$q);

echo 
"\nComparar instancias creadas con parámetros diferentes\n";
compararObjetos($o$p);

echo 
"\nComparar una instancia de una clase padre con una de una subclase\n";
compararObjetos($o$r);
?>

El resultado del ejemplo seria:

Comparar instancias creadas con los mismos parámetros
o1 == o2 : TRUE
o1 != o2 : FALSE
o1 === o2 : TRUE
o1 !== o2 : FALSE

Comparar instancias creadas con parámetros diferentes
o1 == o2 : FALSE
o1 != o2 : TRUE
o1 === o2 : FALSE
o1 !== o2 : TRUE

Comparar una instancia de una clase padre con una de una subclase
o1 == o2 : FALSE
o1 != o2 : TRUE
o1 === o2 : FALSE
o1 !== o2 : TRUE
Que es la salida que podemos esperar dadas las reglas de comparación descritas anteriormente. Solo las instancias con los mismos valores para sus atributos y de la misma clase son consideradas iguales e idénticas.

Incluso en los casos en donde tenemos composición de objetos, se aplican las mismas reglas de comparación. En el ejemplo siguiente creamos una clase contenedora que almacena una matriz asociativa de objetos Bandera.

Example #2 Comparación de objetos compuestos en PHP 4

<?php
class ConjuntoBanderas {
    var 
$conjunto;

    function 
ConjuntoBanderas($matrizBanderas = array()) {
        
$this->conjunto $matrizBanderas;
    }

    function 
agregarBandera($nombre$bandera) {
        
$this->conjunto[$nombre] = $bandera;
    }

    function 
eliminarBandera($nombre) {
        if (
array_key_exists($nombre$this->conjunto)) {
            unset(
$this->conjunto[$nombre]);
        }
    }
}


$u = new ConjuntoBanderas();
$u->agregarBandera('bandera1'$o);
$u->agregarBandera('bandera2'$p);
$v = new ConjuntoBanderas(array('bandera1'=>$q'bandera2'=>$p));
$w = new ConjuntoBanderas(array('bandera1'=>$q));

echo 
"\nObjetos compuestos u(o,p) y v(q,p)\n";
compararObjetos($u$v);

echo 
"\nu(o,p) y w(q)\n";
compararObjetos($u$w);
?>

El resultado del ejemplo seria:

Objetos compuestos u(o,p) y v(q,p)
o1 == o2 : TRUE
o1 != o2 : FALSE
o1 === o2 : TRUE
o1 !== o2 : FALSE

u(o,p) y w(q)
o1 == o2 : FALSE
o1 != o2 : TRUE
o1 === o2 : FALSE
o1 !== o2 : TRUE



Clases y Objetos (PHP 5)> <Clases y Objetos (PHP 4)
Last updated: Fri, 22 Aug 2008
 
add a note add a note User Contributed Notes
Comparación de objetos
Mildred <silkensedai at online dot fr>
16-May-2007 04:17
If you want to test the existance of objects in arrays like in_array but with very strict checking in PHP4 (in order to avoid the "Nesting level too deep - recursive dependency?" error). i wrote the following function.

All objects that can be compared must extends comparable and call the comparable constructor. It will then create a serial number different on each objects.

I don't think it is the ultimate solution because arrays can contains loops and this won't be checked here. And if there is a recursive dependency between objects that do not extends comparable, you will still have the error.

Sometimes I think I don't like PHP very much ...

<?php

class comparable {
   
// Don't forget to call this constructor in sub-classes
   
function comparable(){
        if(!isset(
$GLOBALS[__FILE__.'/class:comparable']))
           
$GLOBALS[__FILE__.'/class:comparable'] = 1;
       
$this->comparableSerial = $GLOBALS[__FILE__.'/class:comparable']++;
    }
}

function
exact_in_array(&$needle, &$haystack){
    foreach(
$haystack as $k=>$v){
       
$elem = &$haystack[$k];
        if(
           
is_object($needle) and is_object($elem) and
           
is_a($needle, 'comparable') and is_a($elem, 'comparable'))
        {
            if(
get_class($needle) === get_class($elem) and
               
$needle->comparableSerial == $elem->comparableSerial)
                return
true;
        }else{
           
// Uncomment this line to know which classes do not extends
            // comparable and fail the test with Nesting level too deep error
            //printf(
            //    "%s(%s) === %s(%s)",
            //    $needle, get_class($needle), $elem, get_class($elem));
           
if($needle === $elem) return true;
        }
        unset(
$elem);
    }
    return
false;
}

?>
magicturkey at gmail dot com
29-Mar-2006 05:15
If youre just checking to see if the variables both reference the same object, instead of having a variable set up beforehand you could do away with the GLOBALS and have something like..
e.g.

<?php
class Foo {
  var
$serial;
  function
Foo() {
  
// Rest of constructor...
 
}
 
// Rest of class definition...
}

$baz->serial = -1;
$bar->serial = time();
if(
$bar->serial == $baz->serial) {
  echo
"Same";
}
?>
pferlet at aston dot fr
29-Apr-2005 02:24
Using globals isn't really well... you can use pattern singleton to verify this.
jazfresh at hotmail dot com
09-Apr-2004 06:44
An addendum to the post below:

If you are comparing two objects and you know that they will be of the same type (you're just not sure if they refer to the same object or not), then there is an easier and faster way to do the comparison, and this also avoids the infinite recursion problem with circular references described in the post below.

In the constructor of your object, set a "serial" attribute from a global variable that is incremented whenever a new object is created. Then you just have to compare serial numbers to see if the objects are the same.

e.g.

<?php
$FooSerial
= 0;
class
Foo {
  var
$serial;
  function
Foo() {
   
$this->serial = $GLOBALS['FooSerial']++;
   
// Rest of constructor...
 
}
 
// Rest of class definition...
}

if(
$bar->serial == $baz->serial) {
  echo
"Same";
}
?>
jazfresh at hotmail dot com
08-Apr-2004 06:18
PHP4 compares two objects (say, $a and $b) by comparing the type and all the attributes. If an attribute is an object, PHP4 will recursively call "if($a.attribute === $b.attribute)" to determine equality. However, this is a problem if a circular reference has been formed. The recursion will go on forever, and you will get the error message:

"Fatal error: Nesting level too deep - recursive dependency?"

Example, where the comparison will never terminate because PHP4 will forever recurse with comparisons of the attribute.
<?php
class Test {
        var
$obj;
}
$foo =& new Test;
$bar =& new Test;
$foo->obj =& $bar; // Make circular reference
$bar->obj =& $foo;

if(
$foo === $bar) {
       
baz();
}
?>
First PHP4 does ($foo === $bar), which expands into ($foo.obj === $bar.obj), which expands into ($bar.obj === $foo.obj), and so on and so on.

To avoid this situation, you must compare objects manually by comparing the two object's attributes and avoiding comparisons on attributes where a circular reference could arise.

This issue is easily avoided in PHP5, where objects can be compared via references rather than the object contents.

Clases y Objetos (PHP 5)> <Clases y Objetos (PHP 4)
Last updated: Fri, 22 Aug 2008
 
 
show source | credits | sitemap | contact | advertising | mirror sites