¿En qué se diferencian los operadores de comparación de igualdad PHP (== doble igual) e identidad (=== triple igual)?

509

¿Cuál es la diferencia entre ==y ===?

  • ¿Cómo funciona exactamente la ==comparación flexible ?
  • ¿Cómo funciona exactamente la ===comparación estricta ?

¿Cuáles serían algunos ejemplos útiles?

nickf
fuente

Respuestas:

633

Diferencia entre ==y===

La diferencia entre el ==operador débilmente igual y el ===operador estrictamente idéntico se explica exactamente en el manual :

Operadores de comparación

┌──────────┬───────────┬────────────────────────── ─────────────────────────────────┐
│ Ejemplo │ Nombre │ Resultado │
├──────────┼───────────┼────────────────────────── ─────────────────────────────────┤
│ $ a == $ b │ Igual │ VERDADERO si $ a es igual a $ b después del malabarismo de tipos. │
│ $ a === $ b │ Idéntico │ VERDADERO si $ a es igual a $ b, y son del mismo tipo. │
└──────────┴───────────┴────────────────────────── ─────────────────────────────────┘

==Comparación libremente igual

Si está utilizando el ==operador, o cualquier otro operador de comparación que utilice una comparación flexible como !=, <>o ==, siempre tiene que mirar el contexto para ver qué, dónde y por qué algo se convierte para comprender lo que está sucediendo.

Convertir reglas

Tabla de comparación de tipos

Como referencia y ejemplo, puede ver la tabla de comparación en el manual :

Comparaciones sueltas con ==

┌─────────┬───────┬───────┬───────┬───────┬─────── ┬───────┬───────┬───────┬───────┬─────────┬─────── ┬───────┐
│ │ VERDADERO │ FALSO │ 1 │ 0 │ -1 │ "1" │ "0" │ "-1" │ NULL │ array () │ "php" │ "" │
├─────────┼───────┼───────┼───────┼───────┼─────── ┼───────┼───────┼───────┼───────┼─────────┼─────── ┼───────┤
│ VERDADERO │ VERDADERO │ FALSO │ VERDADERO │ FALSO │ VERDADERO │ VERDADERO │ FALSO │ VERDADERO │ FALSO │ FALSO │ VERDADERO │ FALSO │
│ FALSO │ FALSO │ VERDADERO │ FALSO │ VERDADERO │ FALSO │ FALSO │ VERDADERO │ FALSO │ VERDADERO │ VERDADERO │ FALSO │ VERDADERO │
│ 1 │ VERDADERO │ FALSO │ VERDADERO │ FALSO │ FALSO │ VERDADERO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │
│ 0 │ FALSO │ VERDADERO │ FALSO │ VERDADERO │ FALSO │ FALSO │ VERDADERO │ FALSO │ VERDADERO │ FALSO │ VERDADERO │ VERDADERO │
│ -1 │ VERDADERO │ FALSO │ FALSO │ FALSO │ VERDADERO │ FALSO │ FALSO │ VERDADERO │ FALSO │ FALSO │ FALSO │ FALSO │
│ "1" │ VERDADERO │ FALSO │ VERDADERO │ FALSO │ FALSO │ VERDADERO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │
│ "0" │ FALSO │ VERDADERO │ FALSO │ VERDADERO │ FALSO │ FALSO │ VERDADERO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │
│ "-1" │ VERDADERO │ FALSO │ FALSO │ FALSO │ VERDADERO │ FALSO │ FALSO │ VERDADERO │ FALSO │ FALSO │ FALSO │ FALSO │
│ NULO │ FALSO │ VERDADERO │ FALSO │ VERDADERO │ FALSO │ FALSO │ FALSO │ FALSO │ VERDADERO │ VERDADERO │ FALSO │ VERDADERO │
│ array () │ FALSO │ VERDADERO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ VERDADERO │ VERDADERO │ FALSO │ FALSO │
│ "php" │ VERDADERO │ FALSO │ FALSO │ VERDADERO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ VERDADERO │ FALSO │
│ "" │ FALSO │ VERDADERO │ FALSO │ VERDADERO │ FALSO │ FALSO │ FALSO │ FALSO │ VERDADERO │ FALSO │ FALSO │ VERDADERO │
└─────────┴───────┴───────┴───────┴───────┴─────── ┴───────┴───────┴───────┴───────┴─────────┴─────── ┴───────┘

Estricta ===comparación idéntica

Si está utilizando el ===operador, o cualquier otro operador de comparación que use una comparación estricta como !==o ===, entonces siempre puede estar seguro de que los tipos no cambiarán mágicamente , porque no habrá conversión. Entonces, con una comparación estricta, el tipo y el valor deben ser los mismos, no solo el valor.

Tabla de comparación de tipos

Como referencia y ejemplo, puede ver la tabla de comparación en el manual :

Estrictas comparaciones con ===

┌─────────┬───────┬───────┬───────┬───────┬─────── ┬───────┬───────┬───────┬───────┬─────────┬─────── ┬───────┐
│ │ VERDADERO │ FALSO │ 1 │ 0 │ -1 │ "1" │ "0" │ "-1" │ NULL │ array () │ "php" │ "" │
├─────────┼───────┼───────┼───────┼───────┼─────── ┼───────┼───────┼───────┼───────┼─────────┼─────── ┼───────┤
│ VERDADERO │ VERDADERO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │
│ FALSO │ FALSO │ VERDADERO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │
│ 1 │ FALSO │ FALSO │ VERDADERO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │
│ 0 │ FALSO │ FALSO │ FALSO │ VERDADERO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │
│ -1 │ FALSO │ FALSO │ FALSO │ FALSO │ VERDADERO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │
│ "1" │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ VERDADERO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │
│ "0" │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ VERDADERO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │
│ "-1" │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ VERDADERO │ FALSO │ FALSO │ FALSO │ FALSO │
│ NULO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ VERDADERO │ FALSO │ FALSO │ FALSO │
│ array () │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ VERDADERO │ FALSO │ FALSO │
│ "php" │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ VERDADERO │ FALSO │
│ "" │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ VERDADERO │
└─────────┴───────┴───────┴───────┴───────┴─────── ┴───────┴───────┴───────┴───────┴─────────┴─────── ┴───────┘
nickf
fuente
66
¿Alguien más encuentra extraño que "000" == "0000"?
nickf
36
Lo que siempre me sorprende es que false == array (), y false == 0 pero array ()! = 0, entonces false == array ()! = / == 0? eso me parece raro
Pim Jager
44
@Pim ... continuación: Míralo de esta manera: lanzando a un BOOL, cualquier valor solo tiene que caer en uno de los dos lados, trueo false. Eso es fácil de lanzar. Sin embargo, todos los demás valores tienen, a todos los efectos prácticos, combinaciones prácticamente ilimitadas. Es "five" == 5? array(0) == 0? array(0,0,0) == 0? 0.0000000000000000000000000000000000000000000000000001 == array()?
deceze
12
@ Raithlin, cuidado con la matriz. triple igual da falsepara diferentes matrices en javascript, pero truepara PHP siempre que sus valores sean iguales .
Pacerier
14
@ Raithlin, muchas más trampas. En JavaScript: "000" != "00" , "000" == null, "000" == false, "0x0" == false, array() == 0, false != null, array() != null, false == "0x0", false == "000". En PHP, que es un comportamiento contrario: "000" == "00" , "000" != null, "000" != false, "0x0" != false, array() != 0, false == null, array() == null, false != "0x0", false != "000".
Pacerier
239

El operador == convierte entre dos tipos diferentes si son diferentes, mientras que el operador === realiza una 'comparación segura de tipos'. Eso significa que solo devolverá verdadero si ambos operandos tienen el mismo tipo y el mismo valor.

Ejemplos:

1 === 1: true
1 == 1: true
1 === "1": false // 1 is an integer, "1" is a string
1 == "1": true // "1" gets casted to an integer, which is 1
"foo" === "foo": true // both operands are strings and have the same value

Advertencia : dos instancias de la misma clase con miembros equivalentes NO coinciden con el ===operador. Ejemplo:

$a = new stdClass();
$a->foo = "bar";
$b = clone $a;
var_dump($a === $b); // bool(false)
Patrick Glandien
fuente
3
Nitpick: === solo devolverá verdadero si ambos operandos son del mismo tipo y los valores son iguales =)
gnud
1
@gnud Eso es exactamente lo que ha mostrado en el ejemplo. Si solo comparara los tipos, simplemente se llamaría una "comparación de tipos", ¿no?
Rob Stevenson-Leggett
3
Después de usar PHP durante 8 años, ayer fue la primera vez que me vi atrapado en una situación en la que debería haber usado ===
3
=== verdadero si son iguales y tienen el mismo tipo. == verdadero si son iguales. ! = verdadero si no son iguales. ! == verdadero si no son iguales o son iguales pero no son del mismo tipo.
Jeremy C
1
Además, usar === es un poco más rápido que == ya que no necesita convertir el valor antes de verificar si es igual.
clauziere
88

Una imagen vale mas que mil palabras:

==Tabla de igualdad de PHP doble igual :

ingrese la descripción de la imagen aquí

===Tabla de igualdad triple de PHP :

ingrese la descripción de la imagen aquí

Código fuente para crear estas imágenes:

https://github.com/sentientmachine/php_equality_charts

Meditación Gurú

Aquellos que desean mantener su cordura, no lean más porque nada de esto tendrá sentido, excepto para decir que así es como se diseñó la locura-fractal de PHP.

  1. NAN != NANpero NAN == true.
  2. ==convertirá los operandos izquierdo y derecho en números si left es un número. Entonces 123 == "123foo", pero"123" != "123foo"
  3. Una cadena hexadecimal entre comillas ocasionalmente es un flotador, y se lanzará por sorpresa flotando contra su voluntad, causando un error de tiempo de ejecución.

  4. ==no es transitivo porque "0"== 0, y 0 == ""pero"0" != ""

  5. Las variables de PHP que aún no se han declarado son falsas, aunque PHP tiene una forma de representar variables indefinidas, esa característica está deshabilitada ==.
  6. "6" == " 6"` "4.2" == "4.20"` y "133" == "0133"pero 133 != 0133. Pero "0x10" == "16"y "1e3" == "1000"exponer esa conversión de cadena sorpresa a octal ocurrirá sin su instrucción o consentimiento, causando un error de tiempo de ejecución.

  7. False == 0, "", []Y "0".

  8. Cuando los números son lo suficientemente grandes, son == Infinito.

  9. Una nueva clase es == a 1.

  10. Falso es el valor más peligroso porque Falso es == para la mayoría de las otras variables, sobre todo para derrotar su propósito.

Esperanza:

Si está utilizando PHP, no utilizará el operador de doble igual porque si utiliza el triple igual, los únicos casos extremos de los que debe preocuparse son NAN y números tan cercanos al infinito que se convierten en infinito. Con dobles iguales, cualquier cosa puede sorprender ==a cualquier cosa, o puede arrojarse por sorpresa contra su voluntad y !=ante algo de lo que obviamente debería ser igual.

Cualquier lugar que use ==en PHP es un mal olor de código debido a los 85 errores expuestos en él por las reglas implícitas de conversión que parecen diseñadas por millones de programadores que programan por movimiento browniano.

Eric Leschinski
fuente
¿Es realmente una buena idea (también segura) usar siempre tres iguales?
Chazy Chaz
3
Sí, la propiedad transitiva de triples iguales lo hace más seguro y escala web.
Eric Leschinski
¿Cómo puede un número estar cerca del infinito? [explosión cerebro gif]
Tim
40

En lo que respecta a JavaScript:

El operador === funciona igual que el operador ==, pero requiere que sus operandos tengan no solo el mismo valor, sino también el mismo tipo de datos.

Por ejemplo, la muestra a continuación mostrará 'x e y son iguales', pero no 'x e y son idénticos'.

var x = 4;
var y = '4';
if (x == y) {
    alert('x and y are equal');
}
if (x === y) {
    alert('x and y are identical');
}
Peter Mortensen
fuente
Upvoted, ya que esto parece ser exactamente la misma situación para php.
David dice que reinstale a Mónica
1
@DavidThomas No es exactamente lo mismo. Ver stackoverflow.com/questions/12598407/…
xdazz
22

Una adición a las otras respuestas sobre la comparación de objetos:

== compara objetos usando el nombre del objeto y sus valores. Si dos objetos son del mismo tipo y tienen los mismos valores de miembro, se $a == $bobtiene verdadero.

=== compara la identificación del objeto interno de los objetos. Incluso si los miembros son iguales, $a !== $bsi no son exactamente el mismo objeto.

class TestClassA {
    public $a;
}

class TestClassB {
    public $a;
}

$a1 = new TestClassA();
$a2 = new TestClassA();
$b = new TestClassB();

$a1->a = 10;
$a2->a = 10;
$b->a = 10;

$a1 == $a1;
$a1 == $a2;  // Same members
$a1 != $b;   // Different classes

$a1 === $a1;
$a1 !== $a2; // Not the same object
soulmerge
fuente
12

En términos más simples:

== comprueba si es equivalente (solo valor)

=== comprueba si el mismo (valor & tipo)


Equivalente frente a igual: una analogía

1 + 1 = 2 + 0 (equivalente)

1 + 1 = 1 + 1 (igual)


En PHP:

verdadero == 1 (verdadero - equivalente en valor)

verdadero === 1 (falso - no es lo mismo en valor && type)

  • verdadero es booleano
  • 1 es int
plata
fuente
"=== comprueba si es el mismo (valor && type)", no exactamente cierto. Dos objetos stdClass tienen el mismo tipo de 'objeto' (es decir, utilizando gettype ()), pero PHP dice que son dos cosas diferentes si usa una comparación estricta. Mira esto .
MAChitgarha
8

Se trata de tipos de datos. Tome un BOOL(verdadero o falso) por ejemplo:

truetambién es igual 1y falsetambién es igual0

El ==no se preocupa por los tipos de datos al comparar: Entonces, si tuviera una variable que sea 1 (que también podría ser true):

$var=1;

Y luego comparar con ==:

if ($var == true)
{
    echo"var is true";
}

Pero en $varrealidad no es igual true, ¿verdad? Tiene el valor int de 1, que a su vez es igual a verdadero.

Con ===, los tipos de datos se verifican para asegurarse de que las dos variables / objetos / lo que sea que estén usando el mismo tipo.

Entonces si lo hiciera

if ($var === true)
{
    echo "var is true";
}

esa condición no sería cierta, ya $var !== trueque solo == true(si sabes a lo que me refiero).

Por qué necesitarías esto?

Simple: echemos un vistazo a una de las funciones de PHP array_search():

La array_search()función simplemente busca un valor en una matriz y devuelve la clave del elemento en el que se encontró el valor. Si no se puede encontrar el valor en la matriz, devuelve falso . Pero, ¿ qué pasaría si hicieras un array_search()valor almacenado en el primer elemento de la matriz (que tendría la clave de matriz de 0...)?array_search() función devolvería 0 ... que es igual a falso ...

Entonces si lo hiciste:

$arr = array("name");
if (array_search("name", $arr) == false)
{
    // This would return 0 (the key of the element the val was found
    // in), but because we're using ==, we'll think the function
    // actually returned false...when it didn't.
}

Entonces, ¿ves cómo esto podría ser un problema ahora?

La mayoría de las personas no usan == falsecuando verifican si una función devuelve falso. En cambio, usan el !. Pero en realidad, esto es exactamente lo mismo que usar ==false, así que si lo hiciste:

$arr = array("name");
if (!array_search("name", $arr)) // This is the same as doing (array_search("name", $arr) == false)

Entonces, para cosas como esa, usaría el ===en su lugar, para que se verifique el tipo de datos.

Peter Mortensen
fuente
8

Un ejemplo es que un atributo de base de datos puede ser nulo o "":

$attributeFromArray = "";
if ($attributeFromArray ==  ""){}  //true
if ($attributeFromArray === ""){}  //true
if ($attributeFromArray ==  null){}  //true
if ($attributeFromArray === null){}  //false

$attributeFromArray = null;
if ($attributeFromArray ==  ""){}  //true
if ($attributeFromArray === ""){}  //false
if ($attributeFromArray ==  null){}  //true
if ($attributeFromArray === null){}  //true
fico7489
fuente
7

php == es un operador de comparación que compara el valor de las variables. Pero === compara el valor y el tipo de datos.

Por ejemplo,

<?php 
  $var1 = 10;
  $var2 = '10';

  if($var1 == $var2) {
    echo 'Variables are equal';
  } else {
    echo 'Variables are not equal';
  }
?>

En este caso, la salida será 'Las variables son iguales', aunque sus tipos de datos sean diferentes.

Pero si usamos === en lugar de ==, la salida será 'Las variables no son iguales'. El php primero compara el valor de la variable y luego el tipo de datos. Aquí los valores son los mismos, pero los tipos de datos son diferentes.

2rahulsk
fuente
6

Dado x = 5

1) Operador: == es "igual a". x == 8es falso
2) Operador: === es "exactamente igual a" (valor y tipo) x === 5es verdadero, x === "5"es falso

Mannusanghi
fuente
3
$a = 5;   // 5 as an integer

var_dump($a == 5);       // compare value; return true
var_dump($a == '5');     // compare value (ignore type); return true
var_dump($a === 5);      // compare type/value (integer vs. integer); return true
var_dump($a === '5');    // compare type/value (integer vs. string); return false

Pero ten cuidado. Aquí hay un problema notorio.

// 'test' is found at position 0, which is interpreted as the boolean 'false'
if (strpos('testing', 'test')) {
    // code...
}

vs.

// true, as strict comparison was made (0 !== false)
if (strpos('testing', 'test') !== false) {
    // code...
}
Seph
fuente
3

En resumen, === funciona de la misma manera que == en la mayoría de los otros lenguajes de programación.

PHP le permite hacer comparaciones que realmente no tienen sentido. Ejemplo:

$y = "wauv";
$x = false;
if ($x == $y)
    ...

Si bien esto permite algunos "atajos" interesantes, debe tener cuidado, ya que una función que devuelve algo que no debería (como "error" en lugar de un número) no quedará atrapada, y se preguntará qué sucedió.

En PHP, == compara valores y realiza la conversión de tipos si es necesario (por ejemplo, la cadena "12343sdfjskfjds" se convertirá en "12343" en una comparación de enteros). === comparará el valor AND type y devolverá false si el tipo no es el mismo.

Si mira el manual de PHP, verá que muchas funciones devuelven "falso" si la función falla, pero podrían devolver 0 en un escenario exitoso, por lo que recomiendan hacer "if (function ()! == falso) "para evitar errores.

Christian P.
fuente
1
Cabe señalar que, además de esos "atajos", se sabe que el comportamiento anormal del operador == abre agujeros de seguridad, por ejemplo, un foro PHP popular donde era posible establecer el valor de hash de la contraseña de cookies en verdadero, eludiendo la validación if (databasehash == cookiehash).
David
3

Pocos ejemplos

var_dump(5 == 5);    // True
var_dump(5 == "5");  // True because == checks only same value not type
var_dump(5 === 5);   // True
var_dump(5 === "5"); // False because value are same but data type are different.

PD

== Solo compara el valor, no se preocupará por los tipos de datos

vs.

=== Compara los valores y tipos de datos

Mohit Tanwani
fuente
¿Cuál es el problema con esta respuesta?
Mohit Tanwani
2

Usaría === para probar si una función o variable es falsa en lugar de simplemente equipararse a falso (cero o una cadena vacía).

$needle = 'a';
$haystack = 'abc';
$pos = strpos($haystack, $needle);
if ($pos === false) {
    echo $needle . ' was not found in ' . $haystack;
} else {
    echo $needle . ' was found in ' . $haystack . ' at location ' . $pos;
}

En este caso, strpos devolvería 0, lo que equivaldría a falso en la prueba

if ($pos == false)

o

if (!$pos)

que no es lo que quieres aquí.

Stacey Richards
fuente
2

En cuanto a cuándo usar uno sobre el otro, tome por ejemplo la fwrite()función en PHP.

Esta función escribe contenido en una secuencia de archivos. Según PHP, " fwrite()devuelve el número de bytes escritos, o FALSO en caso de error". Si desea probar si la llamada a la función fue exitosa, este método es defectuoso:

if (!fwrite(stuff))
{
    log('error!');
}

Puede devolver cero (y se considera exitoso), y su condición aún se activa. La forma correcta sería:

if (fwrite(stuff) === FALSE)
{
    log('error!');
}
Mario
fuente
2

PHP es un lenguaje mecanografiado libremente. El uso del operador de doble igualdad permite una comprobación flexible de una variable.

Si verifica un valor de manera holgada, algunos valores similares, pero no iguales, equivalen a lo mismo:

  • ''
  • nulo
  • falso
  • 0 0

Todos estos valores serían equivalentes como iguales utilizando el operador de doble igual.

Cory Collier
fuente
1

Las variables tienen un tipo y un valor.

  • $ var = "prueba" es una cadena que contiene "prueba"
  • $ var2 = 24 es un número entero cuyo valor es 24.

Cuando usa estas variables (en PHP), a veces no tiene el tipo correcto. Por ejemplo, si lo haces

if ($var == 1) {... do something ...}

PHP tiene que convertir ("emitir") $ var a entero. En este caso, "$ var == 1" es verdadero porque cualquier cadena no vacía se convierte a 1.

Al usar ===, verifica que el valor Y EL TIPO sean iguales, por lo que "$ var === 1" es falso.

Esto es útil, por ejemplo, cuando tiene una función que puede devolver falso (en caso de error) y 0 (resultado):

if(myFunction() == false) { ... error on myFunction ... }

Este código es incorrecto, ya que myFunction()devuelve 0, se convierte en falso y parece tener un error. El código correcto es:

if(myFunction() === false) { ... error on myFunction ... }

porque la prueba es que el valor de retorno "es un valor booleano y es falso" y no "puede convertirse en falso".

ofaurax
fuente
con respecto a las cadenas no vacías, eso en realidad no es cierto. "a" == 0 es VERDADERO.
nickf
1

Se ===supone que el operador compara la igualdad de contenido exacta mientras que el ==operador compararía la igualdad semántica. En particular, obligará a las cadenas a los números.

La igualdad es un tema vasto. Vea el artículo de Wikipedia sobre igualdad .

kmkaplan
fuente
1
<?php

    /**
     * Comparison of two PHP objects                         ==     ===
     * Checks for
     * 1. References                                         yes    yes
     * 2. Instances with matching attributes and its values  yes    no
     * 3. Instances with different attributes                yes    no
     **/

    // There is no need to worry about comparing visibility of property or
    // method, because it will be the same whenever an object instance is
    // created, however visibility of an object can be modified during run
    // time using ReflectionClass()
    // http://php.net/manual/en/reflectionproperty.setaccessible.php
    //
    class Foo
    {
        public $foobar = 1;

        public function createNewProperty($name, $value)
        {
            $this->{$name} = $value;
        }
    }

    class Bar
    {
    }
    // 1. Object handles or references
    // Is an object a reference to itself or a clone or totally a different object?
    //
    //   ==  true   Name of two objects are same, for example, Foo() and Foo()
    //   ==  false  Name of two objects are different, for example, Foo() and Bar()
    //   === true   ID of two objects are same, for example, 1 and 1
    //   === false  ID of two objects are different, for example, 1 and 2

    echo "1. Object handles or references (both == and    ===) <br />";

    $bar = new Foo();    // New object Foo() created
    $bar2 = new Foo();   // New object Foo() created
    $baz = clone $bar;   // Object Foo() cloned
    $qux = $bar;         // Object Foo() referenced
    $norf = new Bar();   // New object Bar() created
    echo "bar";
    var_dump($bar);
    echo "baz";
    var_dump($baz);
    echo "qux";
    var_dump($qux);
    echo "bar2";
    var_dump($bar2);
    echo "norf";
    var_dump($norf);

    // Clone: == true and === false
    echo '$bar == $bar2';
    var_dump($bar == $bar2); // true

    echo '$bar === $bar2';
    var_dump($bar === $bar2); // false

    echo '$bar == $baz';
    var_dump($bar == $baz); // true

    echo '$bar === $baz';
    var_dump($bar === $baz); // false

    // Object reference: == true and === true
    echo '$bar == $qux';
    var_dump($bar == $qux); // true

    echo '$bar === $qux';
    var_dump($bar === $qux); // true

    // Two different objects: == false and === false
    echo '$bar == $norf';
    var_dump($bar == $norf); // false

    echo '$bar === $norf';
    var_dump($bar === $norf); // false

    // 2. Instances with matching attributes and its values (only ==).
    //    What happens when objects (even in cloned object) have same
    //    attributes but varying values?

    // $foobar value is different
    echo "2. Instances with matching attributes  and its values (only ==) <br />";

    $baz->foobar = 2;
    echo '$foobar' . " value is different <br />";
    echo '$bar->foobar = ' . $bar->foobar . "<br />";
    echo '$baz->foobar = ' . $baz->foobar . "<br />";
    echo '$bar == $baz';
    var_dump($bar == $baz); // false

    // $foobar's value is the same again
    $baz->foobar = 1;
    echo '$foobar' . " value is the same again <br />";
    echo '$bar->foobar is ' . $bar->foobar . "<br />";
    echo '$baz->foobar is ' . $baz->foobar . "<br />";
    echo '$bar == $baz';
    var_dump($bar == $baz); // true

    // Changing values of properties in $qux object will change the property
    // value of $bar and evaluates true always, because $qux = &$bar.
    $qux->foobar = 2;
    echo '$foobar value of both $qux and $bar is 2, because $qux = &$bar' . "<br />";
    echo '$qux->foobar is ' . $qux->foobar . "<br />";
    echo '$bar->foobar is ' . $bar->foobar . "<br />";
    echo '$bar == $qux';
    var_dump($bar == $qux); // true

    // 3. Instances with different attributes (only ==)
    //    What happens when objects have different attributes even though
    //    one of the attributes has same value?
    echo "3. Instances with different attributes (only ==) <br />";

    // Dynamically create a property with the name in $name and value
    // in $value for baz object
    $name = 'newproperty';
    $value = null;
    $baz->createNewProperty($name, $value);
    echo '$baz->newproperty is ' . $baz->{$name};
    var_dump($baz);

    $baz->foobar = 2;
    echo '$foobar' . " value is same again <br />";
    echo '$bar->foobar is ' . $bar->foobar . "<br />";
    echo '$baz->foobar is ' . $baz->foobar . "<br />";
    echo '$bar == $baz';
    var_dump($bar == $baz); // false
    var_dump($bar);
    var_dump($baz);
?>
Sathish
fuente
1

Todas las respuestas hasta ahora ignoran un problema peligroso con ===. Se ha notado de pasada, pero no se ha subrayado, que el entero y el doble son tipos diferentes, por lo que el siguiente código:

$n = 1000;
$d = $n + 0.0e0;
echo '<br/>'. ( ($n ==  $d)?'equal' :'not equal' );
echo '<br/>'. ( ($n === $d)?'equal' :'not equal' );

da:

 equal
 not equal

Tenga en cuenta que este NO es un caso de "error de redondeo". Los dos números son exactamente iguales hasta el último bit, pero tienen diferentes tipos.

Este es un problema desagradable porque un programa que usa === puede funcionar felizmente durante años si todos los números son lo suficientemente pequeños (donde "lo suficientemente pequeño" depende del hardware y el sistema operativo en el que se está ejecutando). Sin embargo, si por casualidad, un número entero es lo suficientemente grande como para convertirse en un doble, su tipo se cambia "para siempre" a pesar de que una operación posterior, o muchas operaciones, puede devolverlo a un valor entero pequeño. Y se pone peor. Se puede propagar: la infección por duplicación puede transmitirse a cualquier cosa que toque, un cálculo a la vez.

En el mundo real, es probable que esto sea un problema en los programas que manejan fechas más allá del año 2038, por ejemplo. En este momento, las marcas de tiempo UNIX (número de segundos desde 1970-01-01 00:00:00 UTC) requerirán más de 32 bits, por lo que su representación cambiará "mágicamente" al doble en algunos sistemas. Por lo tanto, si calcula la diferencia entre dos veces, puede terminar con un par de segundos, pero como un doble, en lugar del resultado entero que ocurre en el año 2017.

Creo que esto es mucho peor que las conversiones entre cadenas y números porque es sutil. Me resulta fácil hacer un seguimiento de lo que es una cadena y lo que es un número, pero el seguimiento de la cantidad de bits en un número está más allá de mí.

Entonces, en las respuestas anteriores hay algunas tablas agradables, pero no hay distinción entre 1 (como un entero) y 1 (doble sutil) y 1.0 (doble obvio). Además, los consejos que siempre debes usar === y nunca == no son buenos porque === a veces fallará donde == funciona correctamente. Además, JavaScript no es equivalente a este respecto porque solo tiene un tipo de número (internamente puede tener diferentes representaciones de bits, pero no causa problemas para ===).

Mi consejo: no uses ninguno. Necesitas escribir tu propia función de comparación para realmente arreglar este desastre.

DavidWalley
fuente
0

Hay dos diferencias entre ==y ===en las matrices y objetos PHP que creo que no mencioné aquí; dos matrices con diferentes tipos de teclas y objetos.

Dos matrices con diferentes tipos de teclas.

Si tiene una matriz con una clasificación de claves y otra matriz con una clasificación de claves diferente, son estrictamente diferentes (es decir, usando ===). Eso puede causar si clasifica por clave una matriz e intenta comparar la matriz ordenada con la original.

Por ejemplo, considere una matriz vacía. Primero, intentamos insertar algunos índices nuevos en la matriz sin ningún tipo especial. Un buen ejemplo sería una matriz con cadenas como claves. Ahora en lo profundo de un ejemplo:

// Define an array
$arr = [];

// Adding unsorted keys
$arr["I"] = "we";
$arr["you"] = "you";
$arr["he"] = "they";

Ahora, tenemos una matriz de claves no ordenadas (por ejemplo, 'él' vino después de 'usted'). Considere la misma matriz, pero clasificamos sus claves alfabéticamente:

// Declare array
$alphabetArr = [];

// Adding alphabetical-sorted keys
$alphabetArr["I"] = "we";
$alphabetArr["he"] = "they";
$alphabetArr["you"] = "you";

Consejo : Puede ordenar una matriz por clave usando ksort () .

Ahora tiene otra matriz con un tipo de clave diferente de la primera. Entonces, vamos a compararlos:

$arr == $alphabetArr; // true
$arr === $alphabetArr; // false

Nota : Puede ser obvio, pero la comparación de dos matrices diferentes usando una comparación estricta siempre resulta false. Sin embargo, dos matrices arbitrarias pueden ser iguales usando ===o no.

Diría: "Esta diferencia es insignificante". Entonces digo que es una diferencia y que debe considerarse y puede ocurrir en cualquier momento. Como se mencionó anteriormente, ordenar las claves en una matriz es un buen ejemplo de eso.

Objetos

Tenga en cuenta que dos objetos diferentes nunca son estrictamente iguales . Estos ejemplos ayudarían:

$stdClass1 = new stdClass();
$stdClass2 = new stdClass();
$clonedStdClass1 = clone $stdClass1;

// Comparing
$stdClass1 == $stdClass2; // true
$stdClass1 === $stdClass2; // false
$stdClass1 == $clonedStdClass1; // true
$stdClass1 === $clonedStdClass1; // false

Nota : Asignar un objeto a otra variable no crea una copia, sino que crea una referencia a la misma ubicación de memoria que el objeto. Mira aquí .

Nota : A partir de PHP7, se agregaron clases anónimas . De los resultados, no hay diferencia entre new class {}y new stdClass()en las pruebas anteriores.

MAChitgarha
fuente