In che modo differiscono gli operatori di confronto di uguaglianza PHP (== doppio uguale) e identità (=== triplo uguale)?


509

Qual è la differenza tra ==e ===?

  • Come funziona esattamente il ==confronto vagamente ?
  • Come funziona esattamente il ===confronto rigoroso ?

Quali sarebbero alcuni esempi utili?

Risposte:


633

Differenza tra ==e===

La differenza tra l' ==operatore vagamente uguale e l' ===operatore identico rigoroso è spiegata esattamente nel manuale :

Operatori di confronto

┌──────────┬───────────┬────────────────────────── ─────────────────────────────────┐
│ Esempio │ Nome │ Risultato │
├──────────┼───────────┼────────────────────────── ─────────────────────────────────┤
│ $ a == $ b │ Uguale │ VERO se $ a è uguale a $ b dopo la giocoleria di tipo. │
│ $ a === $ b │ Identico │ VERO se $ a è uguale a $ b, e sono dello stesso tipo. │
└──────────┴───────────┴────────────────────────── ─────────────────────────────────┘

==Confronto vagamente uguale

Se stai usando l' ==operatore, o qualsiasi altro operatore di confronto che utilizza un confronto vagamente come !=, <>o ==, devi sempre guardare il contesto per vedere cosa, dove e perché qualcosa viene convertito per capire cosa sta succedendo.

Conversione di regole

Tabella comparativa dei tipi

Come riferimento ed esempio puoi vedere la tabella di confronto nel manuale :

Confronti sciolti con ==

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

===Confronto identico rigoroso

Se stai utilizzando l' ===operatore o qualsiasi altro operatore di confronto che utilizza un confronto rigoroso come !==o ===, allora puoi sempre essere sicuro che i tipi non cambieranno magicamente , perché non ci sarà alcuna conversione in corso. Quindi, con un rigoroso confronto, il tipo e il valore devono essere gli stessi, non solo il valore.

Tabella comparativa dei tipi

Come riferimento ed esempio puoi vedere la tabella di confronto nel manuale :

Confronti rigorosi con ===

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

66
qualcun altro trova strano che "000" == "0000"?
nickf,

36
Ciò che mi sorprende sempre è che false == array () e false == 0 ma array ()! = 0, quindi false == array ()! = / == 0? mi sembra strano.
Pim Jager,

4
@Pim ... continua: guardalo in questo modo: lanciando su un BOOL, qualsiasi valore deve cadere solo su uno dei due lati, trueoppure false. È facile da lanciare. Tutti gli altri valori hanno, per tutti gli scopi pratici, combinazioni praticamente illimitate. È "five" == 5? array(0) == 0? array(0,0,0) == 0? 0.0000000000000000000000000000000000000000000000000001 == array()?
Inganno

12
@Raithlin, attento all'array. triple equals fornisce falsematrici diverse in javascript, ma trueper PHP purché i loro valori siano uguali .
Pacerier,

14
@Raithlin, molti altri gotchas. In JavaScript: "000" != "00" , "000" == null, "000" == false, "0x0" == false, array() == 0, false != null, array() != null, false == "0x0", false == "000". In PHP, è un comportamento opposto: "000" == "00" , "000" != null, "000" != false, "0x0" != false, array() != 0, false == null, array() == null, false != "0x0", false != "000".
Pacerier,

239

L'operatore == esegue il cast tra due tipi diversi se sono diversi, mentre l'operatore === esegue un "confronto di tipi di errori". Ciò significa che restituirà true solo se entrambi gli operandi hanno lo stesso tipo e lo stesso valore.

Esempi:

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

Avvertenza : due istanze della stessa classe con membri equivalenti NON corrispondono ===all'operatore. Esempio:

$a = new stdClass();
$a->foo = "bar";
$b = clone $a;
var_dump($a === $b); // bool(false)

3
Nitpick: === restituirà vero solo se entrambi gli operandi sono dello stesso tipo e i valori sono uguali =)
gnud,

1
@gnud Questo è esattamente ciò che ha mostrato nell'esempio. Se stesse solo confrontando i tipi, sarebbe semplicemente chiamato un "confronto dei tipi".
Rob Stevenson-Leggett,

3
Dopo aver usato PHP per 8 anni, ieri è stata la prima volta che sono stato catturato in una situazione in cui avrei dovuto usare ===

3
=== vero se sono uguali e hanno lo stesso tipo. == vero se sono uguali. ! = true se non sono uguali. ! == true se non sono uguali o uguali ma non sono dello stesso tipo.
Jeremy C,

1
Inoltre, l'utilizzo di === è leggermente più veloce di == poiché non è necessario convertire il valore prima di verificare se è uguale.
Clauziere,

88

Un'immagine vale più di mille parole:

==Grafico dell'uguaglianza PHP Double Equals :

inserisci qui la descrizione dell'immagine

===Grafico PHP Triple Equals Equality:

inserisci qui la descrizione dell'immagine

Codice sorgente per creare queste immagini:

https://github.com/sentientmachine/php_equality_charts

Guru Meditation

Coloro che desiderano mantenere il loro buonsenso, non leggono oltre perché nulla di tutto ciò avrà alcun senso, tranne per dire che è così che è stato progettato il folle frattale del PHP.

  1. NAN != NANma NAN == true.
  2. ==convertirà gli operandi sinistro e destro in numeri se left è un numero. Quindi 123 == "123foo", ma"123" != "123foo"
  3. Una stringa esadecimale tra virgolette è occasionalmente un float e sarà lanciata a sorpresa per fluttuare contro la tua volontà, causando un errore di runtime.

  4. ==non è transitivo perché "0"== 0, e 0 == ""ma"0" != ""

  5. Le variabili PHP che non sono state ancora dichiarate sono false, anche se PHP ha un modo di rappresentare variabili non definite, questa funzione è disabilitata ==.
  6. "6" == " 6", "4.2" == "4.20"e "133" == "0133"ma 133 != 0133. Ma "0x10" == "16"ed "1e3" == "1000"esporre quella conversione di stringa a sorpresa in ottale avverrà sia senza la tua istruzione che con il tuo consenso, causando un errore di runtime.

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

  8. Quando i numeri sono abbastanza grandi, sono == Infinito.

  9. Una nuova classe è == a 1.

  10. False è il valore più pericoloso perché False è == per la maggior parte delle altre variabili, principalmente annullando il suo scopo.

Speranza:

Se si utilizza PHP, non si utilizzerà l'operatore double egals perché se si utilizzano triple uguale, gli unici casi limite di cui preoccuparsi sono NAN e numeri così vicini all'infinito che vengono lanciati all'infinito. Con il doppio uguale, qualsiasi cosa può essere sorpresa ==a qualsiasi cosa o, o può essere sorpresa, lanciata contro la tua volontà e !=verso qualcosa di cui dovrebbe ovviamente essere uguale.

Ovunque tu usi ==in PHP c'è un cattivo odore di codice a causa degli 85 bug in esso esposti esposti a regole di casting implicite che sembrano progettate da milioni di programmatori che programmano il moto browniano.


È davvero una buona idea (anche sicura) usare sempre triple uguale?
Chazy Chaz,

3
Sì, la proprietà transitiva del triplo uguale lo rende più sicuro e sicuro.
Eric Leschinski,

Come può un numero essere vicino all'infinito? [esplodere cervello gif]
Tim

40

Per quanto riguarda JavaScript:

L'operatore === funziona allo stesso modo dell'operatore ==, ma richiede che i suoi operandi abbiano non solo lo stesso valore, ma anche lo stesso tipo di dati.

Ad esempio, nell'esempio seguente verrà visualizzato "xey sono uguali", ma non "xey y sono identici".

var x = 4;
var y = '4';
if (x == y) {
    alert('x and y are equal');
}
if (x === y) {
    alert('x and y are identical');
}

Eseguito l'upgrade, poiché questa sembra essere esattamente la stessa situazione per php.
David dice di reintegrare Monica il

1
@DavidThomas Non è esattamente la same.See stackoverflow.com/questions/12598407/...
xdazz

22

Un'aggiunta alle altre risposte relative al confronto di oggetti:

== confronta gli oggetti usando il nome dell'oggetto e i loro valori. Se due oggetti sono dello stesso tipo e hanno gli stessi valori dei membri, $a == $bproduce true.

=== confronta l'id interno dell'oggetto degli oggetti. Anche se i membri sono uguali, $a !== $bse non sono esattamente lo stesso oggetto.

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

12

In termini più semplici:

== controlla se equivalente (solo valore)

=== verifica se lo stesso (valore & tipo)


equivalente o uguale: un'analogia

1 + 1 = 2 + 0 (equivalente)

1 + 1 = 1 + 1 (stesso)


in PHP:

true == 1 (true - equivalente in valore)

true === 1 (false - non è lo stesso in value && type)

  • vero è booleano
  • 1 è int

"=== controlla se lo stesso (valore & tipo)", non esattamente vero. Due oggetti stdClass hanno lo stesso tipo di 'oggetto' (cioè usando gettype ()), ma PHP dice che sono due cose diverse se usi un confronto rigoroso. Vedere questo .
MAChitgarha,

8

Si tratta di tipi di dati. Prendi un BOOL(vero o falso) per esempio:

trueanche uguale 1e falseanche uguale0

Al confronto ==non interessano i tipi di dati: Quindi, se avessi una variabile che è 1 (che potrebbe anche essere true):

$var=1;

E quindi confrontare con ==:

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

Ma in $varrealtà non è uguale true, vero? Ha invece il valore int di 1, che a sua volta è uguale a vero.

Con ===, i tipi di dati sono controllati per assicurarsi che le due variabili / oggetti / qualunque cosa stiano usando lo stesso tipo.

Quindi se lo facessi

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

quella condizione non sarebbe vera, in $var !== truequanto solo == true(se sai cosa intendo).

Perché dovresti averne bisogno?

Semplice: diamo un'occhiata a una delle funzioni di PHP array_search():

La array_search()funzione cerca semplicemente un valore in un array e restituisce la chiave dell'elemento in cui è stato trovato il valore. Se il valore non è stato trovato nell'array, restituisce false . Ma cosa succede se si fa un array_search()valore memorizzato nel primo elemento dell'array (che avrebbe la chiave dell'array di 0) .... la array_search()funzione restituirebbe 0 ... che è uguale a false ..

Quindi se hai fatto:

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

Quindi, vedi come questo potrebbe essere un problema ora?

Molte persone non usano == falseper verificare se una funzione restituisce false. Invece, usano il !. Ma in realtà, questo è esattamente uguale all'utilizzo ==false, quindi se hai fatto:

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

Quindi per cose del genere, dovresti usare ===invece, in modo che il tipo di dati sia verificato.


8

Un esempio è che un attributo del database può essere nullo 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

7

php == è un operatore di confronto che confronta il valore delle variabili. Ma === confronta il valore e il tipo di dati.

Per esempio,

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

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

In questo caso l'output sarà "Le variabili sono uguali", anche se i loro tipi di dati sono diversi.

Ma se utilizziamo === anziché ==, l'output sarà "Le variabili non sono uguali". Il php confronta prima il valore della variabile e quindi il tipo di dati. Qui i valori sono gli stessi, ma i tipi di dati sono diversi.


6

Dato x = 5

1) Operatore: == è "uguale a". x == 8è falso
2) Operatore: === è "esattamente uguale a" (valore e tipo) x === 5è vero, x === "5"è falso


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

Stai attento però. Ecco un problema noto.

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

In breve, === funziona allo stesso modo di == nella maggior parte degli altri linguaggi di programmazione.

PHP ti consente di fare confronti che non hanno davvero senso. Esempio:

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

Mentre questo consente alcune "scorciatoie" interessanti, dovresti fare attenzione poiché una funzione che restituisce qualcosa che non dovrebbe (come "errore" anziché un numero) non verrà catturata e ti lascerai a chiederti cosa è successo.

In PHP, == confronta i valori ed esegue la conversione del tipo, se necessario (ad esempio, la stringa "12343sdfjskfjds" diventerà "12343" in un confronto di numeri interi). === confronta il valore AND e restituisce false se il tipo non è lo stesso.

Se guardi nel manuale di PHP, vedrai che molte funzioni restituiscono "false" se la funzione fallisce, ma potrebbero restituire 0 in uno scenario di successo, motivo per cui consigliano di fare "if (function ()! == false) "per evitare errori.


1
Va notato che oltre a quelle "scorciatoie", il comportamento anomalo dell'operatore == è noto per aprire buchi di sicurezza, ad esempio un popolare forum PHP in cui è stato possibile impostare il valore hash della password dei cookie su true, aggirando la convalida if (databasehash == cookiehash).
David,

3

Pochi degli esempi

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

== Confronta solo il valore, non si preoccuperà dei tipi di dati

vs.

=== Confronta i valori e i tipi di dati


qual è il problema con questa risposta?
Mohit Tanwani,

2

Dovresti usare === per verificare se una funzione o una variabile è falsa piuttosto che equivalere a falso (zero o una stringa vuota).

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

In questo caso strpos restituirà 0 che equivarrebbe a false nel test

if ($pos == false)

o

if (!$pos)

che non è quello che vuoi qui.


2

Per quanto riguarda quando usare uno sopra l'altro, prendiamo ad esempio il fwrite() funzione in PHP.

Questa funzione scrive il contenuto in un flusso di file. Secondo PHP, " fwrite()restituisce il numero di byte scritti o FALSE in caso di errore". Se si desidera verificare se la chiamata di funzione ha avuto esito positivo, questo metodo è difettoso:

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

Può restituire zero (ed è considerato corretto) e la tua condizione viene comunque attivata. Il modo giusto sarebbe:

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

2

PHP è un linguaggio vagamente tipizzato. L'uso dell'operatore double equal consente di verificare liberamente una variabile.

Controllare liberamente un valore consentirebbe ad alcuni valori simili, ma non uguali, di eguagliare lo stesso:

  • ''
  • nullo
  • falso
  • 0

Tutti questi valori equivarrebbero come uguali utilizzando l'operatore double equal.


1

Le variabili hanno un tipo e un valore.

  • $ var = "test" è una stringa che contiene "test"
  • $ var2 = 24 è un valore intero vhose è 24.

Quando usi queste variabili (in PHP), a volte non hai il buon tipo. Ad esempio, se lo fai

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

PHP deve convertire ("in cast") $ var in numero intero. In questo caso, "$ var == 1" è vero perché qualsiasi stringa non vuota viene lanciata su 1.

Quando si utilizza ===, si controlla che il valore E IL TIPO siano uguali, quindi "$ var === 1" è falso.

Ciò è utile, ad esempio, quando si dispone di una funzione che può restituire false (in caso di errore) e 0 (risultato):

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

Questo codice è errato come se myFunction()restituisse 0, è impostato su false e sembra che si sia verificato un errore. Il codice corretto è:

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

perché il test è che il valore restituito "è un valore booleano ed è falso" e non "può essere impostato su falso".


per quanto riguarda le stringhe non vuote, in realtà non è vero. "a" == 0 è VERO.
Nickf,

1

L' ===operatore dovrebbe confrontare l' uguaglianza esatta del contenuto mentre l' ==operatore dovrebbe confrontare l'uguaglianza semantica. In particolare costringerà le stringhe ai numeri.

L'uguaglianza è un argomento vasto. Vedi l'articolo di Wikipedia sull'uguaglianza .


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);
?>

1

Tutte le risposte finora ignorano un problema pericoloso con ===. È stato notato di passaggio, ma non sottolineato, che intero e doppio sono tipi diversi, quindi il seguente codice:

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

dà:

 equal
 not equal

Si noti che questo NON è un caso di "errore di arrotondamento". I due numeri sono esattamente uguali fino all'ultimo bit, ma hanno tipi diversi.

Questo è un brutto problema perché un programma che usa === può funzionare felicemente per anni se tutti i numeri sono abbastanza piccoli (dove "abbastanza piccolo" dipende dall'hardware e dal sistema operativo su cui stai eseguendo). Tuttavia, se per caso, un intero risulta abbastanza grande da essere convertito in doppio, il suo tipo viene modificato "per sempre" anche se un'operazione successiva, o molte operazioni, potrebbero riportarlo a un piccolo numero intero. E peggiora. Può diffondersi: l'infezione da doppiazza può essere trasmessa a tutto ciò che tocca, un calcolo alla volta.

Nel mondo reale, questo è probabilmente un problema nei programmi che gestiscono le date oltre l'anno 2038, per esempio. Al momento, i timestamp UNIX (numero di secondi dal 1970-01-01 00:00:00 UTC) richiedono più di 32 bit, quindi la loro rappresentazione "magicamente" passerà al doppio su alcuni sistemi. Pertanto, se si calcola la differenza tra due volte, si potrebbe finire con un paio di secondi, ma come un doppio, anziché il risultato intero che si verifica nell'anno 2017.

Penso che questo sia molto peggio delle conversioni tra stringhe e numeri perché è sottile. Trovo facile tenere traccia di cosa sia una stringa e cosa sia un numero, ma tenere traccia del numero di bit in un numero è oltre me.

Quindi, nelle risposte sopra ci sono alcune belle tabelle, ma nessuna distinzione tra 1 (come un numero intero) e 1 (doppio sottile) e 1.0 (doppio evidente). Inoltre, i consigli che dovresti sempre usare === e mai == non sono grandi perché === a volte fallisce dove == funziona correttamente. Inoltre, JavaScript non è equivalente a questo proposito perché ha solo un tipo di numero (internamente può avere rappresentazioni bit-bit diverse, ma non causa problemi per ===).

Il mio consiglio: non usare nessuno dei due. È necessario scrivere la propria funzione di confronto per risolvere davvero questo casino.


0

Ci sono due differenze tra == e=== in array e oggetti PHP che penso non abbiano menzionato qui; due matrici con diversi tipi di chiavi e oggetti.

Due array con diversi tipi di chiavi

Se si dispone di un array con un ordinamento di chiavi e un altro array con un ordinamento di chiavi diverso, sono rigorosamente differenti (ovvero utilizzando === ). Ciò può causare se si ordina un array di chiavi e si prova a confrontare l'array ordinato con quello originale.

Ad esempio, considera un array vuoto. Innanzitutto, proviamo a inviare alcuni nuovi indici all'array senza alcun ordinamento speciale. Un buon esempio potrebbe essere un array con stringhe come chiavi. Ora in profondità in un esempio:

// Define an array
$arr = [];

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

Ora, abbiamo un array di chiavi non ordinate (ad esempio, "lui" è venuto dopo "te"). Considera lo stesso array, ma abbiamo ordinato le sue chiavi in ​​ordine alfabetico:

// Declare array
$alphabetArr = [];

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

Suggerimento : puoi ordinare un array per chiave usando ksort () .

Ora hai un altro array con un ordinamento di chiavi diverso dal primo. Quindi, li confronteremo:

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

Nota : può essere ovvio, ma il confronto di due array diversi utilizzando un confronto rigoroso risulta sempre false. Tuttavia, due array arbitrari possono essere uguali utilizzando=== o meno.

Diresti: "Questa differenza è trascurabile". Quindi dico che è una differenza e dovrebbe essere considerata e può accadere in qualsiasi momento. Come accennato in precedenza, l'ordinamento delle chiavi in ​​un array ne è un buon esempio.

Oggetti

Tieni presente che due oggetti diversi non sono mai rigorosamente uguali . Questi esempi potrebbero aiutare:

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

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

Nota : l'assegnazione di un oggetto a un'altra variabile non crea una copia, ma crea un riferimento alla stessa posizione di memoria dell'oggetto. Vedere qui .

Nota : a partire da PHP7, sono state aggiunte classi anonime . Dai risultati, non vi è alcuna differenza tra new class {}e new stdClass()nei test sopra.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.