it-swarm-pt.tech

Como o PHP as bases de comparação de igualdade (== duplo é igual a) e identidade (=== triplo é igual) diferem?

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

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

Quais seriam alguns exemplos úteis?

451
nickf

O operador == lança entre dois tipos diferentes se forem diferentes, enquanto o operador === realiza uma 'comparação de tipos'. Isso significa que ele só retornará true se ambos os 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)
235
Patrick Glandien

Uma imagem vale mais que mil palavras:

PHP Double Equals == carta de igualdade:

enter image description here

PHP Triple Equals === Gráfico de igualdade:

enter image description here

Código fonte para criar estas imagens:

https://github.com/sentientmachine/php_equality_charts

Meditação de guru

Aqueles que desejam manter sua sanidade, não leiam mais.

  1. == converte os operandos esquerdo e direito em números quando possível 123 == "123foo", mas "123" != "123foo"
  2. Uma string hexadecimal entre aspas é ocasionalmente um float e será lançada contra a sua vontade.
  3. == não é transitivo porque "0"== 0 e 0 == "" mas "0" != ""
  4. "6" == " 6", "4.2" == "4.20" e "133" == "0133" mas 133 != 0133, porque 0133 é octal. Mas "0x10" == "16" e "1e3" == "1000"
  5. Variáveis ​​PHP que ainda não foram declaradas são falsas.

  6. False == 0, "", [] e "0".

  7. Quando os números são grandes o suficiente, eles são == Infinito.
  8. NAN não == em si, mas é verdade.
  9. Uma aula nova é == para 1.
  10. False é o valor mais perigoso porque False é == para a maioria das outras variáveis, principalmente para derrotar seu propósito.

Esperança:

Se você estiver usando PHP, não usará o operador double equals, use sempre triple equals.

58
Eric Leschinski

Em relação ao JavaScript:

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

Por exemplo, o exemplo abaixo mostrará 'x e y são iguais', mas não 'x e y 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');
}
38
user1684

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

== compara objetos usando o nome do objeto e seus valores. Se dois objetos forem do mesmo tipo e tiverem os mesmos valores de membros, $a == $b produzirá true.

=== compara o ID do objeto interno dos objetos. Mesmo se os membros forem iguais, $a !== $b se eles 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
22
soulmerge

Em termos mais simples:

== verifica se equivalente (apenas valor)

=== verifica se o valor de same (valor && type)


Equivalente vs. Same: Analogia

1 + 1 = 2 + 0 (equivalente)

1 + 1 = 1 + 1 (mesmo)


No PHP:

true == 1 (true - equivalente em valor)

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

  • true é boolean
  • 1 é int
13
silver

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

true também é igual a 1 e false também é igual a 0

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

$var=1;

E então compare com o ==:

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

Mas $var na verdade não é igual a true, não é? Ele tem o valor int de 1, 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 fizesse

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

essa condição não seria verdadeira, pois $var !== true é apenas == true (se você sabe o que quero dizer).

Por que você precisaria disso?

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

A função array_search() 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ê fez um array_search() em um valor que foi armazenado no primeiro elemento da matriz (que teria a chave da matriz 0) .... a função array_search() retornaria 0 ... que é igual a falso ..

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 == false ao verificar se uma função retorna false. Em vez disso, eles usam o !. Mas na verdade, isso é 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)

Então, para coisas desse tipo, você usaria o === em vez disso, para que o tipo de dados fosse verificado.

8
user849137

Um exemplo é que um atributo de 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
8
fico7489

Dado x = 5

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

6
Mannusanghi

Alguns dos 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.

P.S.

== Compara o valor apenas, ele não se importará com os tipos de dados

vs.

=== Compara os valores e tipos de dados

4
Mohit Tanwani

Resumindo, === funciona da mesma maneira que == na maioria das linguagens de programaçã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á detectada, e você ficará imaginando o que aconteceu.

No PHP, == compara valores e executa conversão de tipo, se necessário (por exemplo, a string "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 PHP, verá que muitas funções retornam "false" se a função falhar, mas elas podem retornar 0 em um cenário de sucesso, e é por isso que elas recomendam fazer "if (function () )! == false) "para evitar erros.

3
Christian P.
$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 embora. 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...
}
3
Seph

PHP é uma linguagem fracamente tipada. Usando o operador double equal permite uma verificação solta de uma variável.

Verificar um valor vagamente permitiria que alguns valores semelhantes, mas não iguais, igualassem o mesmo:

  • ''
  • nulo
  • false

Todos esses valores equivalem como iguais usando o operador de dupla igualdade.

2
Cory Collier

Você usaria === para testar se uma função ou variável é falsa em vez de equivale a false (zero ou uma string 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;
}

Neste caso, strpos retornariam 0, o que equivaleria a falso no teste

if ($pos == false)

ou

if (!$pos)

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

2
Stacey Richards

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

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

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

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

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

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 iguais'. O php primeiro compara o valor da variável e, em seguida, o tipo de dados. Aqui os valores são os mesmos, mas os tipos de dados são diferentes.

1
2rahulsk

Todas as respostas até agora ignoram um problema perigoso com ===. Foi observado de passagem, mas não enfatizado, 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

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

Este é um problema desagradável porque um programa usando === pode funcionar felizmente por anos se todos os números forem pequenos o suficiente (onde "pequeno o suficiente" depende do hardware e do sistema operacional que você está usando). No entanto, se por acaso, um número inteiro for grande o suficiente para ser convertido em um duplo, seu tipo será alterado para sempre, mesmo que uma operação subsequente, ou muitas operações, possa trazê-lo de volta para um inteiro pequeno em valor. E fica pior. Ele pode se espalhar - a infecção dupla pode ser transmitida para qualquer coisa que toque, 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 de 2038, por exemplo. Neste momento, os registros de data e hora do UNIX (número de segundos desde 1970-01-01 00:00:00 UTC) exigirão mais de 32 bits, portanto, sua representação será "magicamente" alternada para o dobro em alguns sistemas. Portanto, se você calcular a diferença entre duas vezes, poderá acabar com alguns segundos, mas como um resultado duplo, 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 há algumas tabelas de Nice, mas nenhuma distinção entre 1 (como um inteiro) e 1 (duplo sutil) e 1.0 (duplo óbvio). Além disso, o conselho que você deve sempre usar === e nunca == não é ótimo porque === às vezes falhará onde == funciona corretamente. Além disso, o JavaScript não é equivalente a este respeito, porque ele tem apenas um tipo de número (internamente ele pode ter diferentes representações bit-wise, mas não causa problemas para ===).

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

1
DavidWalley
<?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);
?>
1
Sathish

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

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

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

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

PHP tem que converter ("para lançar") $ var para inteiro. Nesse caso, "$ var == 1" é verdadeiro porque qualquer string não vazia é convertida em 1.

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

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

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

Este código está errado como se myFunction() retornasse 0, fosse convertido para 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 para falso".

1
ofaurax

O operador === deve comparar a igualdade de conteúdo exact enquanto o operador == compararia a igualdade semântica. Em particular, ele irá forçar cadeias de caracteres para números.

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

1
kmkaplan

Existem duas diferenças entre == e === em PHP arrays e objetos que acho que não foram mencionados aqui; dois arrays com diferentes tipos de chaves e objetos.

Dois arrays com diferentes tipos de chaves

Se você tiver uma matriz com uma classificação de chave e outra matriz com uma classificação de chave diferente, elas serão estritamente diferentes (ou seja, usando ===). Isso pode causar se você ordenar uma matriz e tentar comparar a matriz ordenada com a original.

Por exemplo, considere uma matriz vazia. Primeiro, tentamos enviar alguns novos índices para o array sem qualquer tipo especial. Um bom exemplo seria um array com strings como chaves. Agora profundamente 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 ordenadas (por exemplo, "ele" veio depois de "você"). Considere o mesmo array, 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 pela chave usando ksort () function.

Agora você tem outro array com um tipo de chave diferente do primeiro. Então, vamos compará-los:

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

Nota: Pode ser óbvio, mas comparar dois diferentesarrays usando comparação estrita sempre resulta false. No entanto, dois arrays arbitrários podem ser iguais usando === ou não.

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

Objetos

Tenha em mente, dois objetos diferentes nunca são estritamente 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: Atribuir um objeto a outra variável não cria uma cópia - em vez disso, cria uma referência para o 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.

0
MAChitgarha