Como os operadores de comparação de igualdade do PHP (== duplos iguais) e identidade (=== triplos iguais) diferem?

509

Qual é a diferença entre ==e ===?

  • Como exatamente a ==comparação frouxa funciona?
  • Como exatamente a ===comparação estrita funciona?

Quais seriam alguns exemplos úteis?

nickf
fonte

Respostas:

633

Diferença entre ==e===

A diferença entre o ==operador frouxamente igual e o ===operador estritamente idêntico é explicada exatamente no manual :

Operadores de comparação

┌────────────────────────────────────────────────────── ────────────────────────────────┐
│ Exemplo │ Nome │ Resultado │
├────────────────────────────────────────────────────── ────────────────────────────────┤
│ $ a == $ b │ Igual │ TRUE se $ a for igual a $ b após o malabarismo do tipo. │
A $ a === $ b │ Idêntico │ TRUE se $ a for igual a $ b, e eles são do mesmo tipo. │
└────────────────────────────────────────────────────── ────────────────────────────────┘

==Comparação fracamente igual

Se você estiver usando o ==operador, ou qualquer outro operador de comparação que faça comparações frouxas, como !=, <>ou ==, você sempre precisará olhar o contexto para ver o que, onde e por que algo é convertido para entender o que está acontecendo.

Convertendo regras

Tabela de comparação de tipos

Como referência e exemplo, você pode ver a tabela de comparação no manual :

Comparações frouxas com ==

┌────────────────┬──────────────────────────────────────────────── ┬───────┬──────────────┬───────┬──────────────────────────── ┬───────┐
│ UE TRUE │ FALSE │ 1 │ -1 │ "1" 0 "0" │ "-1" │ NULL │ array () │ "php" │ "" │
├────────────────┼───────┼────────────────────────────────── ┼───────┼───────┼──────┼───────┼───────────────────────────── ┼───────┤
│ VERDADEIRO │ VERDADEIRO AL FALSO │ VERDADEIRO │ FALSO │ VERDADEIRO │ VERDADEIRO AL FALSO │ VERDADEIRO │ FALSO │ FALSO │ VERDADEIRO │ FALSO │
│ FALSO │ FALSO │ VERDADEIRO │ FALSO │ VERDADEIRO │ FALSO │ FALSO │ VERDADEIRO │ FALSO │ VERDADEIRO │ VERDADEIRO │ FALSO │ VERDADEIRO │
│ 1 │ VERDADEIRO AL FALSO │ VERDADEIRO │ FALSO │ FALSO │ VERDADEIRO AL FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │
│ 0 │ FALSO │ VERDADEIRO │ FALSO │ VERDADEIRO │ FALSO │ FALSO UE VERDADEIRO │ FALSO │ VERDADEIRO AL FALSO │ VERDADEIRO │ VERDADEIRO │
│ -1 │ VERDADEIRO AL FALSO │ FALSO │ FALSO │ VERDADEIRO AL FALSO │ FALSO │ VERDADEIRO │ FALSO │ FALSO │ FALSO │ FALSO │
1 "1" │ VERDADEIRO │ FALSO │ VERDADEIRO │ FALSO │ FALSO │ VERDADEIRO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │
0 "0" │ FALSO │ VERDADEIRO AL FALSO │ VERDADEIRO │ FALSO │ FALSO │ VERDADEIRO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │
-1 "-1" │ VERDADEIRO │ FALSO │ FALSO │ FALSO │ VERDADEIRO AL FALSO │ FALSO │ VERDADEIRO │ FALSO │ FALSO │ FALSO │ FALSO │
│ NULL │ FALSO │ VERDADEIRO AL FALSO │ VERDADEIRO │ FALSO │ FALSO │ FALSO │ FALSO │ VERDADEIRO │ VERDADEIRO │ FALSO │ VERDADEIRO │
│ matriz () │ FALSO │ VERDADEIRO AL FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ VERDADEIRO │ VERDADEIRO │ FALSO │ FALSO │
Ph "php" │ VERDADEIRO │ FALSO │ FALSO │ VERDADEIRO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ VERDADEIRO │ FALSO │
│ "" │ FALSO │ VERDADEIRO │ FALSO │ VERDADEIRO │ FALSO │ FALSO │ FALSO │ FALSO │ VERDADEIRO AL FALSO │ FALSO │ VERDADEIRO │
└────────────────┴───────┴────────────────────────────────── ┴───────┴───────┴──────┴───────┴───────────────────────────── ┴───────┘

===Comparação estrita e idêntica

Se você estiver usando o ===operador, ou qualquer outro operador de comparação que use comparação estrita como !==ou ===, poderá sempre ter certeza de que os tipos não serão alterados magicamente , porque não haverá conversão em andamento. Portanto, com comparação estrita, o tipo e o valor devem ser os mesmos, não apenas o valor.

Tabela de comparação de tipos

Como referência e exemplo, você pode ver a tabela de comparação no manual :

Comparações rigorosas com ===

┌────────────────┬──────────────────────────────────────────────── ┬───────┬──────────────┬───────┬──────────────────────────── ┬───────┐
│ UE TRUE │ FALSE │ 1 │ -1 │ "1" 0 "0" │ "-1" │ NULL │ array () │ "php" │ "" │
├────────────────┼───────┼────────────────────────────────── ┼───────┼───────┼──────┼───────┼───────────────────────────── ┼───────┤
│ VERDADEIRO │ VERDADEIRO AL FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │
│ FALSO │ FALSO │ VERDADEIRO AL FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │
│ 1 │ FALSO │ FALSO │ VERDADEIRO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │
│ 0 │ FALSO │ FALSO │ FALSO │ VERDADEIRO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │
│ -1 AL FALSO │ FALSO │ FALSO │ VERDADEIRO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │
1 "1" │ FALSO │ FALSO │ FALSO │ FALSO │ VERDADEIRO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │
0 "0" │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ VERDADEIRO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │
-1 "-1" │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ VERDADEIRO AL FALSO │ FALSO │ FALSO │ FALSO │
│ NULL │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ VERDADEIRO │ FALSO │ FALSO │ FALSO │
│ matriz () │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ VERDADEIRO │ FALSO │ FALSO │
Ph "php" │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ VERDADEIRO │ FALSO │
│ "" │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO AL FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ FALSO │ VERDADEIRO │
└────────────────┴───────┴────────────────────────────────── ┴───────┴───────┴──────┴───────┴───────────────────────────── ┴───────┘
nickf
fonte
66
alguém mais acha estranho "000" == "0000"?
nickf
36
O que sempre me surpreende é que false == array () e false == 0 mas array ()! = 0, então false == array ()! = / == 0? isso me parece estranho.
Pim Jager
4
@Pim ... continuação: veja desta maneira: convertendo para um BOOL, qualquer valor só precisa cair em um dos dois lados, trueou false. Isso é fácil de lançar. Todos os outros valores têm, para todos os efeitos práticos, combinações praticamente ilimitadas. É "five" == 5? array(0) == 0? array(0,0,0) == 0? 0.0000000000000000000000000000000000000000000000000001 == array()?
Deceze
12
@ Raithlin, cuidado com a matriz. triple igual dá falsepara diferentes matrizes em javascript, mas truepara PHP desde que seus valores sejam iguais .
Pacerier
14
@ Raithlin, muitos outros truques. Em JavaScript: "000" != "00" , "000" == null, "000" == false, "0x0" == false, array() == 0, false != null, array() != null, false == "0x0", false == "000". Em PHP, é o comportamento oposto: "000" == "00" , "000" != null, "000" != false, "0x0" != false, array() != 0, false == null, array() == null, false != "0x0", false != "000".
Pacerier 07/08
239

O operador == lança entre dois tipos diferentes, se forem diferentes, enquanto o operador === realiza uma 'comparação de segurança de tipo'. Isso significa que ele só retornará true se os dois operandos tiverem o mesmo tipo e o mesmo valor.

Exemplos:

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

Aviso : duas instâncias da mesma classe com membros equivalentes NÃO correspondem ao ===operador. Exemplo:

$a = new stdClass();
$a->foo = "bar";
$b = clone $a;
var_dump($a === $b); // bool(false)
Patrick Glandien
fonte
3
Nitpick: === só retornará verdadeiro se ambos os operandos são do mesmo tipo e os valores são iguais =)
gnud
1
@gnud Isso é exatamente o que ele mostrou no exemplo. Se apenas comparássemos os tipos, seria apenas chamado de "comparação de tipos".
26411 Rob Stevenson-Leggett
3
Depois de usar o PHP para 8 anos, ontem foi a primeira vez que eu fui pego em uma situação onde eu deveria ter usado ===
3
=== true se eles são iguais e têm o mesmo tipo. == true se eles são iguais. ! = true se não forem iguais. ! == true se eles não são iguais ou são iguais, mas não são do mesmo tipo.
Jeremy C
1
Além disso, usar === é um pouco mais rápido que ==, pois não precisa converter o valor antes de verificar se é igual.
clauziere
88

Uma imagem vale mais que mil palavras:

==Gráfico de igualdade PHP Double Equals :

insira a descrição da imagem aqui

===Gráfico de igualdade tripla de PHP :

insira a descrição da imagem aqui

Código fonte para criar estas imagens:

https://github.com/sentientmachine/php_equality_charts

meditação de guru

Aqueles que desejam manter sua sanidade mental não leem mais, porque nada disso fará sentido, exceto para dizer que foi assim que o fractal de insanidade do PHP foi projetado.

  1. NAN != NANmas NAN == true.
  2. ==converterá operandos esquerdo e direito em números se esquerda for um número. Então 123 == "123foo"mas"123" != "123foo"
  3. Uma sequência hexadecimal entre aspas é ocasionalmente uma flutuação e será lançada surpresa para flutuar contra sua vontade, causando um erro de tempo de execução.

  4. ==não é transitivo porque "0"== 0, 0 == ""mas"0" != ""

  5. Variáveis ​​PHP que ainda não foram declaradas são falsas, mesmo que o PHP tenha uma maneira de representar variáveis ​​indefinidas, esse recurso está desativado ==.
  6. "6" == " 6",, "4.2" == "4.20"e "133" == "0133"mas 133 != 0133. Mas "0x10" == "16"e "1e3" == "1000"expondo que a conversão corda surpresa para octal irá ocorrer tanto sem a sua instrução ou consentimento, causando um erro de execução.

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

  8. Quando os números são grandes o suficiente, eles são == Infinito.

  9. Uma nova classe é == para 1.

  10. Falso é o valor mais perigoso, porque Falso é == para a maioria das outras variáveis, derrotando principalmente seu objetivo.

Esperança:

Se você estiver usando PHP, você não usará o operador double igual, porque se você usar o triplo é igual, os únicos casos em que você deve se preocupar são NAN e números tão próximos do infinito que são convertidos no infinito. Com duplos iguais, qualquer coisa pode ser surpresa ==para qualquer coisa ou, ou pode ser lançada contra a sua vontade e !=para algo que obviamente deveria ser igual.

Qualquer lugar que você usa ==no PHP tem um cheiro ruim de código por causa dos 85 bugs nele expostos por regras implícitas de elenco que parecem projetadas por milhões de programadores programando por movimento browniano.

Eric Leschinski
fonte
É realmente uma boa ideia (também segura) sempre usar iguais triplos?
precisa saber é o seguinte
3
Sim, a propriedade transitiva de triplos iguais o torna mais seguro e em escala da web.
Eric Leschinski
Como um número pode estar próximo ao infinito? [gif explodindo cérebro]
Tim
40

Em relação ao JavaScript:

O operador === funciona da mesma forma que o operador ==, mas exige que seus operandos não tenham apenas o mesmo valor, mas também o mesmo tipo de dados.

Por exemplo, a amostra abaixo exibirá 'xey são iguais', mas não 'xey são 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
fonte
Voto positivo, pois parece ser exatamente a mesma situação para php.
David diz que restabelece Monica
1
@DavidThomas Não é exatamente o same.See stackoverflow.com/questions/12598407/...
xdazz
22

Uma adição às outras respostas relacionadas à comparação de objetos:

== compara objetos usando o nome do objeto e seus valores. Se dois objetos são do mesmo tipo e têm os mesmos valores de membro, $a == $bproduz true.

=== compara o ID interno do objeto. Mesmo se os membros forem iguais, $a !== $bse não forem exatamente o mesmo 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
fonte
12

Em termos mais simples:

== verifica se equivalente (somente valor)

=== verifica se o mesmo (tipo valor e&) é


equivalente vs. igual : uma analogia

1 + 1 = 2 + 0 (equivalente)

1 + 1 = 1 + 1 (o mesmo)


No PHP:

true == 1 (verdadeiro - equivalente em valor)

true === 1 (false - não é o mesmo em value && type)

  • verdadeiro é booleano
  • 1 é int
prata
fonte
"=== verifica se o mesmo (tipo valor e&)", não exatamente verdadeiro. Dois objetos stdClass têm o mesmo tipo de 'objeto' (ou seja, usando gettype ()), mas o PHP diz que são duas coisas diferentes se você usar uma comparação estrita. Veja isso .
MAChitgarha
8

É tudo sobre tipos de dados. Tome um BOOL(verdadeiro ou falso), por exemplo:

truetambém é igual 1e falsetambém é igual0

O ==não se importa com os tipos de dados ao comparar: Portanto, se você tivesse uma variável que seja 1 (que também poderia ser true):

$var=1;

E então compare com o ==:

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

Mas $varna verdade não é igual true, não é? Em 1vez disso, possui o valor int , que, por sua vez, é igual a true.

Com ===, os tipos de dados são verificados para garantir que as duas variáveis ​​/ objetos / o que quer que esteja usando o mesmo tipo.

Então se eu fiz

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

essa condição não seria verdadeira, como $var !== trueapenas == true(se você entende o que quero dizer).

Por que você precisaria disso?

Simples - vamos dar uma olhada em uma das funções do PHP array_search():

A array_search()função simplesmente procura um valor em uma matriz e retorna a chave do elemento em que o valor foi encontrado. Se o valor não puder ser encontrado na matriz, ele retornará false . Mas, e se você fizesse array_search()um valor armazenado no primeiro elemento da matriz (que teria a chave da matriz 0) .... a array_search()função retornaria 0 ... que é igual a false ..

Então, se você fez:

$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.
}

Então, você vê como isso pode ser um problema agora?

A maioria das pessoas não usa == falseao verificar se uma função retorna false. Em vez disso, eles usam o !. Mas, na verdade, é exatamente o mesmo que usar ==false, então se você fez:

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

Portanto, para coisas assim, você usaria o em ===vez disso, para que o tipo de dados seja verificado.

Peter Mortensen
fonte
8

Um exemplo é que um atributo do banco de dados pode ser nulo ou "":

$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
fonte
7

php == é um operador de comparação que compara o valor das variáveis. Mas === compara o valor e o tipo de dados.

Por exemplo,

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

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

Nesse caso, a saída será 'Variáveis ​​iguais', mesmo que seus tipos de dados sejam diferentes.

Mas se usarmos === em vez de ==, a saída será 'Variáveis ​​não são iguais'. O php compara primeiro o valor da variável e depois o tipo de dados. Aqui os valores são iguais, mas os tipos de dados são diferentes.

2rahulsk
fonte
6

Dado x = 5

1) Operador: == é "igual a". x == 8é falso
2) Operador: === é "exatamente igual a" (valor e tipo) x === 5é verdadeiro, x === "5"é falso

Mannusanghi
fonte
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

Tenha cuidado, porém. Aqui está um problema notório.

// '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
fonte
3

Em resumo, o === funciona da mesma maneira que o == na maioria das outras linguagens de programação.

O PHP permite que você faça comparações que realmente não fazem sentido. Exemplo:

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

Embora isso permita alguns "atalhos" interessantes, você deve tomar cuidado, pois uma função que retorna algo que não deveria (como "erro" em vez de um número) não será capturada e você ficará se perguntando o que aconteceu.

No PHP, == compara valores e executa conversão de tipo, se necessário (por exemplo, a cadeia "12343sdfjskfjds" se tornará "12343" em uma comparação inteira). === irá comparar o valor AND type e retornará false se o tipo não for o mesmo.

Se você olhar no manual do PHP, verá que muitas funções retornam "false" se a função falhar, mas podem retornar 0 em um cenário bem-sucedido, e é por isso que recomendam "if (function ()! == false) "para evitar erros.

Christian P.
fonte
1
Deve-se observar que, além desses "atalhos", sabe-se que o comportamento anormal do operador == abre brechas de segurança, por exemplo, um fórum PHP popular onde era possível definir o valor do hash da senha dos cookies como true, contornando a validação if (databasehash == cookiehash).
David
3

Poucos exemplos

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.

PS

== Compara apenas o valor, não se preocupa com os tipos de dados

vs.

=== Compara os valores e tipos de dados

Mohit Tanwani
fonte
qual é o problema com esta resposta?
Mohit Tanwani
2

Você usaria === para testar se uma função ou variável é falsa, em vez de apenas igualar a falsa (zero ou uma sequência vazia).

$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;
}

Nesse caso, strpos retornaria 0, o que equivaleria a falso no teste

if ($pos == false)

ou

if (!$pos)

o que não é o que você quer aqui.

Stacey Richards
fonte
2

Quanto a quando usar um sobre o outro, considere, por exemplo, a fwrite()função em PHP.

Esta função grava conteúdo em um fluxo de arquivos. De acordo com o PHP, " fwrite()retorna o número de bytes gravados, ou FALSE em erro.". Se você deseja testar se a chamada de função foi bem-sucedida, este método é defeituoso:

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

Pode retornar zero (e é considerado bem-sucedido) e sua condição ainda é acionada. O caminho certo seria:

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

PHP é uma linguagem pouco tipada. O uso do operador double equal permite uma verificação solta de uma variável.

Verificar livremente um valor permitiria que alguns valores semelhantes, mas não iguais, fossem iguais:

  • ''
  • nulo
  • falso
  • 0 0

Todos esses valores seriam iguais como iguais usando o operador double equal.

Cory Collier
fonte
1

Variáveis ​​têm um tipo e um valor.

  • $ var = "test" é uma string que contém "test"
  • $ var2 = 24 é um número inteiro cujo valor é 24.

Quando você usa essas variáveis ​​(em PHP), às vezes você não tem o tipo bom. Por exemplo, se você fizer

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

O PHP precisa converter ("converter") $ var para inteiro. Nesse caso, "$ var == 1" é verdadeiro porque qualquer sequência não vazia é convertida em 1.

Ao usar ===, você verifica se o valor AND THE TYPE é igual; portanto, "$ var === 1" é falso.

Isso é útil, por exemplo, quando você tem uma função que pode retornar false (em erro) e 0 (resultado):

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

Esse código está errado como se myFunction()retornasse 0, foi convertido em false e você parece ter um erro. O código correto é:

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

porque o teste é que o valor de retorno "é um booleano e é falso" e não "pode ​​ser convertido em falso".

ofaurax
fonte
com relação a cadeias não vazias, isso não é verdade. "a" == 0 é VERDADEIRO.
nickf
1

o === operador deve comparar a igualdade exata de conteúdo, enquanto o ==operador compararia a igualdade semântica. Em particular, ele coagirá as strings a números.

A igualdade é um assunto vasto. Veja o artigo da Wikipedia sobre igualdade .

kmkaplan
fonte
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
fonte
1

Até agora, todas as respostas ignoram um problema perigoso com ===. Foi observado de passagem, mas não estressado, que inteiro e duplo são tipos diferentes, portanto, o seguinte código:

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

dá:

 equal
 not equal

Observe que este NÃO é um caso de "erro de arredondamento". Os dois números são exatamente iguais até o último bit, mas eles têm tipos diferentes.

Esse é um problema desagradável, porque um programa usando === pode ser executado felizmente por anos se todos os números forem pequenos o suficiente (onde "pequeno o suficiente" depende do hardware e do sistema operacional em que você está executando). No entanto, se por acaso um número inteiro for grande o suficiente para ser convertido em um dobro, seu tipo será alterado "para sempre", mesmo que uma operação subsequente, ou muitas operações, possa trazê-lo de volta para um número inteiro pequeno. E fica pior. Pode se espalhar - a infecção por duplicidade pode ser transmitida para qualquer coisa que tocar, um cálculo de cada vez.

No mundo real, é provável que isso seja um problema em programas que lidam com datas além do ano 2038, por exemplo. No momento, os carimbos de data e hora do UNIX (número de segundos desde 01-01-2009 00:00:00 UTC) exigirão mais de 32 bits; portanto, sua representação mudará "magicamente" para dobrar em alguns sistemas. Portanto, se você calcular a diferença entre duas vezes, poderá acabar com alguns segundos, mas como um dobro, em vez do resultado inteiro que ocorre no ano de 2017.

Eu acho que isso é muito pior do que conversões entre strings e números, porque é sutil. Acho fácil acompanhar o que é uma string e o que é um número, mas acompanhar o número de bits em um número está além de mim.

Portanto, nas respostas acima, existem algumas tabelas agradáveis, mas nenhuma distinção entre 1 (como número inteiro) e 1 (duplo sutil) e 1,0 (duplo óbvio). Além disso, o conselho de que você sempre deve usar === e nunca == não é ótimo, porque === às vezes falha quando o == funciona corretamente. Além disso, o JavaScript não é equivalente a esse respeito, pois possui apenas um tipo de número (internamente, pode ter diferentes representações em bits, mas não causa problemas para ===).

Meu conselho - não use nenhum. Você precisa escrever sua própria função de comparação para realmente consertar essa bagunça.

DavidWalley
fonte
0

Existem duas diferenças entre ==e=== nas matrizes e objetos PHP que acho que não foram mencionados aqui; duas matrizes com diferentes tipos de chave e objetos.

Duas matrizes com diferentes tipos de chave

Se você possui uma matriz com uma classificação de chave e outra matriz com uma classificação de chave diferente, elas são estritamente diferentes (por exemplo, usando ===). Isso pode causar se você classificar uma matriz com chave e tentar comparar a matriz classificada com a matriz original.

Por exemplo, considere uma matriz vazia. Primeiro, tentamos enviar alguns novos índices para a matriz sem nenhum tipo especial. Um bom exemplo seria uma matriz com cadeias de caracteres como chaves. Agora, em um exemplo:

// Define an array
$arr = [];

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

Agora, temos uma matriz de chaves não classificadas (por exemplo, 'ele' veio depois de 'você'). Considere a mesma matriz, mas classificamos suas chaves em ordem alfabética:

// Declare array
$alphabetArr = [];

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

Dica : Você pode classificar uma matriz por chave usando ksort () função .

Agora você tem outra matriz com uma classificação de chave diferente da primeira. Então, vamos compará-los:

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

Nota : Pode ser óbvio, mas comparar duas matrizes diferentes usando sempre comparação estrita resulta false. No entanto, duas matrizes arbitrárias podem ser iguais usando ===ou não.

Você diria: "Essa diferença é insignificante". Então eu digo que é uma diferença e deve ser considerada e pode acontecer a qualquer momento. Como mencionado acima, a classificação de chaves em uma matriz é um bom exemplo disso.

Objetos

Lembre-se de que dois objetos diferentes nunca são iguais . Esses exemplos ajudariam:

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

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

Nota : A atribuição de um objeto a outra variável não cria uma cópia; em vez disso, cria uma referência ao mesmo local de memória que o objeto. Veja aqui .

Nota : A partir do PHP7, classes anônimas foram adicionadas. A partir dos resultados, não há diferença entre new class {}e new stdClass()nos testes acima.

MAChitgarha
fonte