En quoi les opérateurs de comparaison d'égalité PHP (== double égal) et d'identité (=== triple égal) diffèrent-ils?

509

Quelle est la difference entre ==et ===?

  • Comment fonctionne exactement la ==comparaison lâche ?
  • Comment fonctionne exactement la ===comparaison stricte ?

Quels seraient des exemples utiles?

nickf
la source

Réponses:

633

Différence entre == et===

La différence entre l' ==opérateur vaguement égal et l' ===opérateur strictement identique est expliquée exactement dans le manuel :

Opérateurs de comparaison

┌──────────┬───────────┬────────────────────────── ──────────────────────────────────┐
│ Exemple │ Nom │ Résultat │
├──────────┼───────────┼────────────────────────── ──────────────────────────────────┤
│ $ a == $ b │ Égal │ VRAI si $ a est égal à $ b après avoir jonglé avec le type. │
│ $ a === $ b │ Identique │ VRAI si $ a est égal à $ b et qu'ils sont du même type. │
└──────────┴───────────┴────────────────────────── ──────────────────────────────────┘

Librement ==Comparaison égale

Si vous utilisez l' ==opérateur, ou tout autre opérateur de comparaison qui utilise une comparaison lâche comme !=, <>ou ==, vous devez toujours regarder le contexte pour voir quoi, où et pourquoi quelque chose est converti pour comprendre ce qui se passe.

Conversion des règles

Tableau de comparaison des types

Comme référence et exemple, vous pouvez voir le tableau de comparaison dans le manuel :

Comparaisons lâches avec ==

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

===Comparaison strictement identique

Si vous utilisez l' ===opérateur, ou tout autre opérateur de comparaison qui utilise une comparaison stricte comme !==ou ===, alors vous pouvez toujours être sûr que les types ne changeront pas comme par magie , car il n'y aura pas de conversion en cours. Donc, avec une comparaison stricte, le type et la valeur doivent être les mêmes, pas seulement la valeur.

Tableau de comparaison des types

Comme référence et exemple, vous pouvez voir le tableau de comparaison dans le manuel :

Comparaisons strictes avec ===

┌─────────┬───────┬───────┬───────┬────────┬─────── ┬───────┬───────┬───────┬───────┬──────────┬─────── ┬───────┐
│ │ VRAI │ FAUX │ 1 │ 0 │ -1 │ "1" │ "0" │ "-1" │ NULL │ tableau () │ "php" │ "" │
├─────────┼───────┼───────┼───────┼────────┼─────── ┼───────┼───────┼───────┼───────┼──────────┼─────── ┼───────┤
│ VRAI │ VRAI │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │
│ FAUX │ FAUX │ VRAI │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │
│ 1 │ FAUX │ FAUX │ VRAI │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │
│ 0 │ FAUX │ FAUX │ FAUX │ VRAI │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │
│ -1 │ FAUX │ FAUX │ FAUX │ FAUX │ VRAI │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │
│ "1" │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ VRAI │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │
│ "0" │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ VRAI │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │
│ "-1" │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ VRAI │ FAUX │ FAUX │ FAUX │ FAUX │
│ NULL │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ VRAI │ FAUX │ FAUX │ FAUX │
│ array () │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ VRAI │ FAUX │ FAUX │
│ "php" │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ VRAI │ FAUX │
│ "" │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ FAUX │ VRAI │
└─────────┴───────┴───────┴───────┴────────┴─────── ┴───────┴───────┴───────┴───────┴──────────┴─────── ┴───────┘
nickf
la source
66
quelqu'un d'autre trouve-t-il étrange que "000" == "0000"?
nickf
36
Ce qui me surprend toujours, c'est que false == array (), et false == 0 mais array ()! = 0, donc false == array ()! = / == 0? ça me fait bizarre.
Pim Jager
4
@Pim ... suite: Regardez-le de cette façon: Casting à un BOOL, n'importe quelle valeur ne doit tomber que sur un des deux côtés, trueou false. C'est facile à lancer. Toutes les autres valeurs ont cependant, à toutes fins pratiques, des combinaisons pratiquement illimitées. Est-ce "five" == 5? array(0) == 0? array(0,0,0) == 0? 0.0000000000000000000000000000000000000000000000000001 == array()?
décomposer
12
@Raithlin, attention au tableau. triple égal donne falsepour différents tableaux en javascript, mais truepour PHP tant que leurs valeurs sont égales .
Pacerier
14
@Raithlin, Beaucoup d'autres accrochages. JavaScript: "000" != "00" , "000" == null, "000" == false, "0x0" == false, array() == 0, false != null, array() != null, false == "0x0", false == "000". En PHP, il est un comportement contraire: "000" == "00" , "000" != null, "000" != false, "0x0" != false, array() != 0, false == null, array() == null, false != "0x0", false != "000".
Pacerier
239

L'opérateur == effectue une conversion entre deux types différents s'ils sont différents, tandis que l'opérateur === effectue une «comparaison sécurisée des types». Cela signifie qu'il ne retournera true que si les deux opérandes ont le même type et la même valeur.

Exemples:

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

Avertissement : deux instances de la même classe avec des membres équivalents NE correspondent PAS à l' ===opérateur. Exemple:

$a = new stdClass();
$a->foo = "bar";
$b = clone $a;
var_dump($a === $b); // bool(false)
Patrick Glandien
la source
3
Nitpick: === ne retournera true que si les deux opérandes sont du même type et que les valeurs sont égales =)
gnud
1
@gnud C'est exactement ce qu'il a montré dans l'exemple. S'il s'agissait simplement de comparer les types, cela serait simplement appelé une "comparaison de types", n'est-ce pas?
Rob Stevenson-Leggett
3
Après avoir utilisé PHP pendant 8 ans, hier était la première fois que je me
3
=== vrai s'ils sont égaux et ont le même type. == vrai s'ils sont égaux. ! = vrai s'ils ne sont pas égaux. ! == true si elles ne sont pas égales ou sont égales mais ne sont pas du même type.
Jeremy C
1
En outre, l'utilisation de === est légèrement plus rapide que == car elle n'a pas besoin de convertir la valeur avant de vérifier si elle est égale.
clauziere
88

Une image vaut mieux que mille mots:

==Tableau d'égalité PHP Double Equals :

entrez la description de l'image ici

===Graphique d'égalité triple PHP :

entrez la description de l'image ici

Code source pour créer ces images:

https://github.com/sentientmachine/php_equality_charts

Guru Meditation

Ceux qui souhaitent garder leur raison, ne lisent pas plus loin car rien de tout cela n'aura de sens, sauf pour dire que c'est ainsi que la folie fractale de PHP a été conçue.

  1. NAN != NANmais NAN == true.
  2. ==convertira les opérandes gauche et droite en nombres si gauche est un nombre. Alors 123 == "123foo", mais"123" != "123foo"
  3. Une chaîne hexadécimale entre guillemets est parfois un flottant, et sera lancée par surprise pour flotter contre votre volonté, provoquant une erreur d'exécution.

  4. ==n'est pas transitif parce que "0"== 0, 0 == ""mais"0" != ""

  5. Les variables PHP qui n'ont pas encore été déclarées sont fausses, même si PHP a un moyen de représenter des variables non définies, cette fonctionnalité est désactivée avec ==.
  6. "6" == " 6",, "4.2" == "4.20"et "133" == "0133"mais 133 != 0133. Mais "0x10" == "16"et "1e3" == "1000"exposer cette conversion de chaîne surprise en octal se produira sans votre instruction ou votre consentement, provoquant une erreur d'exécution.

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

  8. Lorsque les nombres sont assez grands, ils sont == Infinity.

  9. Une nouvelle classe est == à 1.

  10. False est la valeur la plus dangereuse car False est == pour la plupart des autres variables, la plupart du temps son objectif est vaincu.

Espérer:

Si vous utilisez PHP, vous n'utiliserez pas l'opérateur double égal car si vous utilisez triple égal, les seuls cas marginaux à craindre sont NAN et les nombres si proches de l'infini qu'ils sont convertis à l'infini. Avec un double égal, tout peut être une surprise ==pour n'importe quoi ou, ou peut être lancé par surprise contre votre volonté et !=pour quelque chose dont il devrait évidemment être égal.

Partout où vous utilisez ==en PHP est une mauvaise odeur de code en raison des 85 bogues qui y sont exposés par des règles de casting implicites qui semblent conçues par des millions de programmeurs programmant par mouvement brownien.

Eric Leschinski
la source
Est-ce vraiment une bonne idée (également sécurisée) de toujours utiliser le triple égal?
Chazy Chaz
3
Oui, la propriété transitive du triple égal le rend plus sécurisé et à l'échelle du Web.
Eric Leschinski
Comment un nombre peut-il être proche de l'infini? [Gif du cerveau qui explose]
Tim
40

En ce qui concerne JavaScript:

L'opérateur === fonctionne de la même manière que l'opérateur ==, mais il requiert que ses opérandes aient non seulement la même valeur, mais également le même type de données.

Par exemple, l'exemple ci-dessous affichera «x et y sont égaux», mais pas «x et y sont identiques».

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
la source
Voté, car cela semble être exactement la même situation pour php.
David dit de réintégrer Monica
1
@DavidThomas Ce n'est pas exactement la même chose. Voir stackoverflow.com/questions/12598407/…
xdazz
22

Un complément aux autres réponses concernant la comparaison d'objets:

== compare les objets en utilisant le nom de l'objet et leurs valeurs. Si deux objets sont du même type et ont les mêmes valeurs de membre, $a == $brenvoie true.

=== compare l'ID d'objet interne des objets. Même si les membres sont égaux, $a !== $bs'ils ne sont pas exactement le même objet.

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
la source
12

En termes simples:

== vérifie s'il est équivalent (valeur uniquement)

=== vérifie si le même (valeur et type)


équivalent ou identique: une analogie

1 + 1 = 2 + 0 (équivalent)

1 + 1 = 1 + 1 (même)


En PHP:

true == 1 (true - valeur équivalente)

true === 1 (false - pas la même valeur & type)

  • vrai est booléen
  • 1 est int
argent
la source
"=== vérifie si la même chose (valeur && type)", pas exactement vrai. Deux objets stdClass ont le même type d '«objet» (c'est-à-dire en utilisant gettype ()), mais PHP dit que ce sont deux choses différentes si vous utilisez une comparaison stricte. Regardez ça .
MAChitgarha
8

Tout dépend des types de données. Prenez un BOOL(vrai ou faux) par exemple:

trueest également égal à 1et falseégalement égal à0

Le ==ne se soucie pas des types de données lors de la comparaison: Donc, si vous aviez une variable qui est 1 (qui pourrait également être true):

$var=1;

Et puis comparez avec ==:

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

Mais ce $varn'est pas vraiment égal true, n'est-ce pas? Il a la valeur int de 1au lieu de cela, qui à son tour, est égale à true.

Avec ===, les types de données sont vérifiés pour s'assurer que les deux variables / objets / quoi que ce soit utilisent le même type.

Donc si je le faisais

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

cette condition ne serait pas vraie, car $var !== trueelle seule == true(si vous voyez ce que je veux dire).

Pourquoi en auriez-vous besoin?

Simple - jetons un œil à l'une des fonctions de PHP array_search()::

La array_search()fonction recherche simplement une valeur dans un tableau et renvoie la clé de l'élément dans lequel la valeur a été trouvée. Si la valeur est introuvable dans le tableau, elle renvoie false . Mais que se passe-t-il si vous faites une array_search()sur une valeur stockée dans le premier élément du tableau (qui aurait la clé du tableau de 0) .... la array_search()fonction retournera 0 ... ce qui est égal à false ..

Donc si vous l'avez fait:

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

Alors, voyez-vous comment cela pourrait être un problème maintenant?

La plupart des gens ne l'utilisent pas == falsepour vérifier si une fonction retourne false. Au lieu de cela, ils utilisent le !. Mais en fait, c'est exactement la même chose que l'utilisation ==false, donc si vous l'avez fait:

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

Donc, pour des choses comme ça, vous utiliseriez à la ===place, afin que le type de données soit vérifié.

Peter Mortensen
la source
8

Un exemple est qu'un attribut de base de données peut être nul 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
la source
7

php == est un opérateur de comparaison qui compare la valeur des variables. Mais === compare la valeur et le type de données.

Par exemple,

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

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

Dans ce cas, la sortie sera «Les variables sont égales», même si leurs types de données sont différents.

Mais si nous utilisons === au lieu de ==, la sortie sera «Les variables ne sont pas égales». Le php compare d'abord la valeur de la variable puis le type de données. Ici, les valeurs sont identiques, mais les types de données sont différents.

2rahulsk
la source
6

Donné x = 5

1) Opérateur: == est "égal à". x == 8est faux
2) Opérateur: === est "exactement égal à" (valeur et type) x === 5est vrai, x === "5"est faux

Mannusanghi
la source
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

Soyez prudent cependant. Voici un problème notoire.

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

contre.

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

En bref, === fonctionne de la même manière que == dans la plupart des autres langages de programmation.

PHP vous permet de faire des comparaisons qui n'ont pas vraiment de sens. Exemple:

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

Bien que cela permette des "raccourcis" intéressants, vous devez vous méfier car une fonction qui renvoie quelque chose qu'il ne devrait pas (comme "erreur" au lieu d'un nombre) ne sera pas interceptée, et vous vous demanderez ce qui s'est passé.

En PHP, == compare les valeurs et effectue une conversion de type si nécessaire (par exemple, la chaîne "12343sdfjskfjds" deviendra "12343" dans une comparaison entière). === comparera la valeur AND type et retournera false si le type n'est pas le même.

Si vous regardez dans le manuel PHP, vous verrez que beaucoup de fonctions retournent "false" si la fonction échoue, mais elles peuvent retourner 0 dans un scénario réussi, c'est pourquoi elles recommandent de faire "if (function ()! == false) "pour éviter les erreurs.

Christian P.
la source
1
Il convient de noter qu'en plus de ces "raccourcis", le comportement anormal de l'opérateur == est connu pour ouvrir des failles de sécurité, par exemple un forum PHP populaire où il était possible de définir la valeur de hachage du mot de passe des cookies sur true, en contournant la validation if (databasehash == cookiehash).
David
3

Quelques exemples

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

== Compare la valeur uniquement, il ne se souciera pas des types de données

contre.

=== Compare les valeurs et les types de données

Mohit Tanwani
la source
quel est le problème avec cette réponse?
Mohit Tanwani
2

Vous utiliseriez === pour tester si une fonction ou une variable est fausse plutôt que de simplement assimiler false (zéro ou une chaîne vide).

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

Dans ce cas, strpos renverrait 0, ce qui équivaudrait à faux dans le test

if ($pos == false)

ou

if (!$pos)

ce n'est pas ce que vous voulez ici.

Stacey Richards
la source
2

Quant à savoir quand utiliser l'un sur l'autre, prenez par exemple la fwrite()fonction en PHP.

Cette fonction écrit du contenu dans un flux de fichiers. Selon PHP, " fwrite()renvoie le nombre d'octets écrits, ou FAUX en cas d'erreur.". Si vous souhaitez tester si l'appel de fonction a réussi, cette méthode est défectueuse:

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

Il peut retourner zéro (et est considéré comme réussi) et votre condition est toujours déclenchée. La bonne façon serait:

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

PHP est un langage peu typé. L'utilisation de l'opérateur double égal permet une vérification lâche d'une variable.

Une vérification lâche d'une valeur permettrait à certaines valeurs similaires, mais pas égales, d'être égales comme les mêmes:

  • ''
  • nul
  • faux
  • 0

Toutes ces valeurs seraient égales comme égales en utilisant l'opérateur double égal.

Cory Collier
la source
1

Les variables ont un type et une valeur.

  • $ var = "test" est une chaîne qui contient "test"
  • $ var2 = 24 est un entier dont la valeur est 24.

Lorsque vous utilisez ces variables (en PHP), parfois vous n'avez pas le bon type. Par exemple, si vous le faites

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

PHP doit convertir ("to cast") $ var en entier. Dans ce cas, "$ var == 1" est vrai car toute chaîne non vide est convertie en 1.

Lorsque vous utilisez ===, vous vérifiez que la valeur ET LE TYPE sont égaux, donc "$ var === 1" est faux.

Ceci est utile, par exemple, lorsque vous avez une fonction qui peut retourner false (en cas d'erreur) et 0 (résultat):

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

Ce code est incorrect car s'il myFunction()renvoie 0, il est converti en false et vous semblez avoir une erreur. Le bon code est:

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

car le test est que la valeur de retour "est un booléen et est faux" et non "peut être convertie en faux".

ofaurax
la source
en ce qui concerne les chaînes non vides, ce n'est en fait pas vrai. "a" == 0 est VRAI.
nickf
1

L' ===opérateur est censé comparer l' égalité de contenu exacte tandis que l' ==opérateur comparerait l'égalité sémantique. En particulier, il contraindra les chaînes aux nombres.

L'égalité est un vaste sujet. Voir l'article Wikipedia sur l'égalité .

kmkaplan
la source
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
la source
1

Jusqu'à présent, toutes les réponses ignorent un problème dangereux avec ===. Il a été noté au passage, mais non souligné, que entier et double sont de types différents, donc le code suivant:

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

donne:

 equal
 not equal

Notez qu'il ne s'agit PAS d'une "erreur d'arrondi". Les deux nombres sont exactement égaux jusqu'au dernier bit, mais ils ont des types différents.

Il s'agit d'un problème désagréable car un programme utilisant === peut fonctionner correctement pendant des années si tous les nombres sont suffisamment petits (où "assez petit" dépend du matériel et du système d'exploitation sur lesquels vous exécutez). Cependant, si par hasard, un entier se trouve être suffisamment grand pour être converti en double, son type est changé "pour toujours" même si une opération ultérieure, ou de nombreuses opérations, pourrait le ramener à un petit entier en valeur. Et ça empire. Elle peut se propager - une infection à double nesse peut être transmise à tout ce qu'elle touche, un calcul à la fois.

Dans le monde réel, cela risque d'être un problème dans les programmes qui gèrent des dates au-delà de l'année 2038, par exemple. À l'heure actuelle, les horodatages UNIX (nombre de secondes depuis 1970-01-01 00:00:00 UTC) nécessiteront plus de 32 bits, de sorte que leur représentation passera "comme par magie" pour doubler sur certains systèmes. Par conséquent, si vous calculez la différence entre deux fois, vous pourriez vous retrouver avec quelques secondes, mais en double, plutôt que le résultat entier qui se produit en 2017.

Je pense que c'est bien pire que les conversions entre chaînes et nombres car c'est subtil. Je trouve facile de garder une trace de ce qu'est une chaîne et ce qui est un nombre, mais garder une trace du nombre de bits dans un nombre me dépasse.

Ainsi, dans les réponses ci-dessus, il y a de belles tables, mais aucune distinction entre 1 (comme un entier) et 1 (double subtil) et 1.0 (double évident). De plus, les conseils que vous devez toujours utiliser === et jamais == ne sont pas excellents car === échouera parfois là où == fonctionne correctement. De plus, JavaScript n'est pas équivalent à cet égard car il n'a qu'un seul type de nombre (en interne, il peut avoir différentes représentations bit à bit, mais il ne pose pas de problème pour ===).

Mon conseil - n'utilisez ni l'un ni l'autre. Vous devez écrire votre propre fonction de comparaison pour vraiment corriger ce gâchis.

DavidWalley
la source
0

Il y a deux différences entre ==et ===dans les tableaux et objets PHP que je ne pense pas mentionner ici; deux tableaux avec différents types de clés et objets.

Deux tableaux avec différents types de clés

Si vous avez un tableau avec un tri de clé et un autre tableau avec un tri de clé différent, ils sont strictement différents (c'est-à-dire en utilisant ===). Cela peut provoquer si vous triez un tableau par clé et essayez de comparer le tableau trié avec le tableau d'origine.

Par exemple, considérez un tableau vide. Tout d'abord, nous essayons de pousser de nouveaux index vers le tableau sans aucun tri spécial. Un bon exemple serait un tableau avec des chaînes comme clés. Maintenant profondément dans un exemple:

// Define an array
$arr = [];

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

Maintenant, nous avons un tableau de clés non triées (par exemple, «il» est venu après «vous»). Considérez le même tableau, mais nous avons trié ses clés par ordre alphabétique:

// Declare array
$alphabetArr = [];

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

Astuce : vous pouvez trier un tableau par clé à l'aide de ksort () .

Vous avez maintenant un autre tableau avec un tri de clé différent du premier. Nous allons donc les comparer:

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

Remarque : Cela peut être évident, mais la comparaison de deux tableaux différents en utilisant une comparaison stricte entraîne toujours false. Cependant, deux tableaux arbitraires peuvent être égaux en utilisant ===ou non.

Vous diriez: "Cette différence est négligeable". Ensuite, je dis que c'est une différence et doit être considérée et peut se produire à tout moment. Comme mentionné ci-dessus, le tri des clés dans un tableau en est un bon exemple.

Objets

Gardez à l'esprit que deux objets différents ne sont jamais strictement égaux . Ces exemples pourraient aider:

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

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

Remarque : L'affectation d'un objet à une autre variable ne crée pas de copie - elle crée plutôt une référence au même emplacement mémoire que l'objet. Voyez ici .

Remarque : Depuis PHP7, des classes anonymes ont été ajoutées. D'après les résultats, il n'y a aucune différence entre new class {}et new stdClass()dans les tests ci-dessus.

MAChitgarha
la source