Czym różnią się operatory porównania równości PHP (== podwójne równe) i tożsamości (=== trzyosobowe)?


Odpowiedzi:


633

Różnica między ==i===

Różnica między luźno ==równym operatorem a ściśle ===identycznym operatorem została dokładnie wyjaśniona w instrukcji :

Operatory porównania

┌──────────┬───────────┬────────────────────────── ─────────────────────────────────┐
│ Przykład │ Nazwa │ Wynik │
├──────────┼───────────┼────────────────────────── ─────────────────────────────────┤
│ $ a == $ b │ Równe │ PRAWDA, jeśli $ a jest równe $ b po żonglowaniu typem. │
│ $ a === $ b │ Identyczne │ PRAWDA, jeśli $ a jest równe $ b i są tego samego typu. │
└──────────┴───────────┴────────────────────────── ─────────────────────────────────┘

Luźno ==równe porównanie

Jeśli używasz ==operatora, lub dowolny inny operator porównania, które wykorzystuje luźno porównanie takie jak !=, <>lub ==, zawsze trzeba spojrzeć na kontekst , aby zobaczyć, co, gdzie i dlaczego coś zostanie przekonwertowany do zrozumienia tego, co się dzieje.

Konwertowanie reguł

Tabela porównawcza typów

Jako odniesienie i przykład możesz zobaczyć tabelę porównawczą w instrukcji :

Luźne porównania z ==

┌─────────┬───────┬───────┬───────┬───────┬─────── ┬───────┬───────┬───────┬───────┬─────────┬─────── ┬───────┐
│ │ PRAWDA │ FAŁSZ │ 1 │ 0 │ -1 │ „1” │ „0” │ „-1” │ NULL │ tablica () │ „php” │ „” │
├─────────┼───────┼───────┼───────┼───────┼─────── ┼───────┼───────┼───────┼───────┼─────────┼─────── ┼───────┤
│ PRAWDA │ PRAWDA │ FAŁSZ │ PRAWDA │ FAŁSZ │ PRAWDA │ PRAWDA │ FAŁSZ │ PRAWDA │ FAŁSZ │ FAŁSZ │ PRAWDA │ FAŁSZ │
│ FAŁSZ │ FAŁSZ │ PRAWDA │ FAŁSZ │ PRAWDA │ FAŁSZ │ FAŁSZ │ PRAWDA │ FAŁSZ │ PRAWDA │ PRAWDA │ FAŁSZ │ PRAWDA │
│ 1 │ PRAWDA │ FAŁSZ │ PRAWDA │ FAŁSZ │ FAŁSZ │ PRAWDA │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │
│ 0 │ FAŁSZ │ PRAWDA │ FAŁSZ │ PRAWDA │ FAŁSZ │ FAŁSZ │ PRAWDA │ FAŁSZ │ PRAWDA │ FAŁSZ │ PRAWDA │ PRAWDA │
│ -1 │ PRAWDA │ FAŁSZ │ FAŁSZ │ FAŁSZ │ PRAWDA │ FAŁSZ │ FAŁSZ │ PRAWDA │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │
│ „1” │ PRAWDA │ FAŁSZ │ PRAWDA │ FAŁSZ │ FAŁSZ │ PRAWDA │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │
│ „0” │ FAŁSZ │ PRAWDA │ FAŁSZ │ PRAWDA │ FAŁSZ │ FAŁSZ │ PRAWDA │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │
│ „-1” │ PRAWDA │ FAŁSZ │ FAŁSZ │ FAŁSZ │ PRAWDA │ FAŁSZ │ FAŁSZ │ PRAWDA │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │
│ NULL │ FAŁSZ │ PRAWDA │ FAŁSZ │ PRAWDA │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ PRAWDA │ PRAWDA │ FAŁSZ │ PRAWDA │
│ array () │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ TRUE │ FALSE │ FALSE │
Ph „php” │ PRAWDA │ FAŁSZ │ FAŁSZ │ PRAWDA │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ PRAWDA │ FAŁSZ │
│ „” │ FAŁSZ │ PRAWDA │ FAŁSZ │ PRAWDA │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ PRAWDA │ FAŁSZ │ FAŁSZ │ PRAWDA │
└─────────┴───────┴───────┴───────┴───────┴─────── ┴───────┴───────┴───────┴───────┴─────────┴─────── ┴───────┘

Ścisłe ===identyczne porównanie

Jeśli używasz ===operatora lub dowolnego innego operatora porównania, który używa ścisłego porównania, takiego jak !==lub ===, zawsze możesz być pewien, że typy nie zmienią się magicznie , ponieważ nie nastąpi konwersja. Zatem przy ścisłym porównaniu typ i wartość muszą być takie same, a nie tylko wartość.

Tabela porównawcza typów

Jako odniesienie i przykład możesz zobaczyć tabelę porównawczą w instrukcji :

Ścisłe porównania z ===

┌─────────┬───────┬───────┬───────┬───────┬─────── ┬───────┬───────┬───────┬───────┬─────────┬─────── ┬───────┐
│ │ PRAWDA │ FAŁSZ │ 1 │ 0 │ -1 │ „1” │ „0” │ „-1” │ NULL │ tablica () │ „php” │ „” │
├─────────┼───────┼───────┼───────┼───────┼─────── ┼───────┼───────┼───────┼───────┼─────────┼─────── ┼───────┤
│ PRAWDA │ PRAWDA │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │
│ FAŁSZ │ FAŁSZ │ PRAWDA │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │
│ 1 │ FAŁSZ │ FAŁSZ │ PRAWDA │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │
│ 0 │ FAŁSZ │ FAŁSZ │ FAŁSZ │ PRAWDA │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │
│ -1 │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ PRAWDA │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │
│ „1” │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ PRAWDA │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │
│ „0” │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ PRAWDA │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │
│ „-1” │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ PRAWDA │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │
│ NULL │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ PRAWDA │ FAŁSZ │ FAŁSZ │ FAŁSZ │
│ array () │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │
Ph „php” │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ PRAWDA │ FAŁSZ │
│ „” AL FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ FAŁSZ │ PRAWDA │
└─────────┴───────┴───────┴───────┴───────┴─────── ┴───────┴───────┴───────┴───────┴─────────┴─────── ┴───────┘

65
czy ktokolwiek inny uważa za dziwne, że „000” == „0000”?
nickf

36
Zawsze mnie zaskakuje to, że false == array () i false == 0 ale array ()! = 0, więc false == array ()! = / == 0? to wydaje mi się dziwne.
Pim Jager,

4
@Pim ... ciąg dalszy: Spójrz na to w ten sposób: Przesyłając do BOOL, każda wartość musi spaść tylko z jednej lub dwóch stron, truelub false. Łatwo to rzucić. Jednak wszystkie inne wartości mają praktycznie nieograniczoną liczbę kombinacji. Jest "five" == 5? array(0) == 0? array(0,0,0) == 0? 0.0000000000000000000000000000000000000000000000000001 == array()?
deceze

12
@Raithlin, uważaj na tablicę. triple equals daje falseróżne tablice w javascript, ale truedla PHP, o ile ich wartości są równe .
Pacerier

14
@Raithlin, Wiele, wiele innych gotchas. W JavaScript: "000" != "00" , "000" == null, "000" == false, "0x0" == false, array() == 0, false != null, array() != null, false == "0x0", false == "000". W PHP, to naprzeciwko zachowanie: "000" == "00" , "000" != null, "000" != false, "0x0" != false, array() != 0, false == null, array() == null, false != "0x0", false != "000".
Pacerier,

239

Operator == rzuca między dwoma różnymi typami, jeśli są one różne, podczas gdy operator === wykonuje „porównanie typów”. Oznacza to, że zwróci prawdę tylko wtedy, gdy oba operandy mają ten sam typ i tę samą wartość.

Przykłady:

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

Ostrzeżenie : dwa wystąpienia tej samej klasy z równoważnymi elementami NIE są zgodne z ===operatorem. Przykład:

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

3
Nitpick: === zwróci wartość true tylko wtedy, gdy oba operandy są tego samego typu, a wartości są równe =)
gnud

1
@gnud Dokładnie to pokazano w przykładzie. Gdyby tylko porównywał typy, nazwałby to „porównaniem typów”, prawda?
Rob Stevenson-Leggett

3
Po 8 latach korzystania z PHP wczoraj po raz pierwszy złapałem się w sytuacji, w której powinienem był używać ===

3
=== true, jeśli są równe i mają ten sam typ. == true, jeśli są równe. ! = prawda, jeśli nie są równe. ! == true, jeśli albo nie są równe, albo są równe, ale nie są tego samego typu.
Jeremy C

1
Ponadto użycie === jest nieco szybsze niż ==, ponieważ nie trzeba konwertować wartości przed sprawdzeniem, czy jest równa.
clauziere

88

Obraz jest wart tysiąca słów:

==Tabela równości PHP Double Equals :

wprowadź opis zdjęcia tutaj

PHP Triple Equals ===Equality wykres:

wprowadź opis zdjęcia tutaj

Kod źródłowy, aby utworzyć te obrazy:

https://github.com/sentientmachine/php_equality_charts

Medytacja Guru

Ci, którzy chcą zachować zdrowie psychiczne, nie czytają dalej, ponieważ nic z tego nie będzie miało sensu, z wyjątkiem twierdzenia, że ​​tak zaprojektowano fraktal szaleństwa PHP.

  1. NAN != NANale NAN == true.
  2. ==konwertuje lewy i prawy operand na liczby, jeśli lewy jest liczbą. No 123 == "123foo"ale"123" != "123foo"
  3. Ciąg szesnastkowy w cudzysłowie jest czasem zmiennoprzecinkowy i będzie niespodziewanie rzucany, aby unosić się wbrew twojej woli, powodując błąd w czasie wykonywania.

  4. ==nie jest przechodnie, ponieważ "0"== 0i 0 == ""ale"0" != ""

  5. Zmienne PHP, które nie zostały jeszcze zadeklarowane, są fałszywe, mimo że PHP ma sposób reprezentowania niezdefiniowanych zmiennych, funkcja ta jest wyłączona ==.
  6. "6" == " 6", "4.2" == "4.20"i "133" == "0133"ale 133 != 0133. Ale "0x10" == "16"i "1e3" == "1000"wystawienie takiej konwersji niespodzianka ciąg do ósemkowej wystąpią zarówno bez instrukcji lub zgody, powodując błąd wykonania.

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

  8. Gdy liczby są wystarczająco duże, to == nieskończoność.

  9. Świeża klasa to == do 1.

  10. Fałsz jest najbardziej niebezpieczną wartością, ponieważ Fałsz jest == dla większości innych zmiennych, głównie pokonując swój cel.

Nadzieja:

Jeśli używasz PHP, nie powinieneś używać operatora podwójnej równości, ponieważ jeśli używasz potrójnej równości, jedynymi przypadkami, o które należy się martwić, są NAN i liczby tak bliskie nieskończoności, że są rzutowane na nieskończoność. W przypadku podwójnych równości wszystko może być niespodzianką ==dla każdego lub może być niespodzianką rzuconą wbrew twojej woli i !=na coś, co oczywiście powinno być równe.

W każdym miejscu, w którym używasz ==PHP, jest nieprzyjemny zapach kodu z powodu 85 błędów w nim ujawnionych przez niejawne reguły rzutowania, które wydają się projektowane przez miliony programistów programujących ruchem Brownian.


Czy to naprawdę dobry pomysł (również bezpieczny), aby zawsze używać potrójnych równych?
Chazy Chaz

3
Tak, przechodnia właściwość potrójnej równości sprawia, że ​​jest bezpieczniejsza i skalowana w sieci.
Eric Leschinski

Jak liczba może być bliska nieskończoności? [wybuchający gif mózgu]
Tim

40

W odniesieniu do JavaScript:

Operator === działa tak samo jak operator ==, ale wymaga, aby jego operandy miały nie tylko tę samą wartość, ale także ten sam typ danych.

Na przykład poniższa próbka wyświetli „xiy są równe”, ale nie „xiy są identyczne”.

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

Pozytywne, ponieważ wydaje się, że jest to dokładnie taka sama sytuacja w przypadku php.
David mówi, że przywraca Monikę

1
@DavidThomas To nie jest dokładnie to samo. Zobacz stackoverflow.com/questions/12598407/…
xdazz

22

Dodatek do innych odpowiedzi dotyczących porównania obiektów:

== porównuje obiekty na podstawie nazwy obiektu i ich wartości. Jeśli dwa obiekty są tego samego typu i mają te same wartości $a == $bskładowe , zwraca true.

=== porównuje wewnętrzny identyfikator obiektu dla obiektów. Nawet jeśli członkowie są równi, $a !== $bjeśli nie są dokładnie tym samym przedmiotem.

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

Mówiąc najprościej:

== sprawdza, czy ekwiwalent (tylko wartość)

=== sprawdza, czy ten sam (wartość i typ)


Odpowiednik kontra taki sam: analogia

1 + 1 = 2 + 0 (odpowiednik)

1 + 1 = 1 + 1 (to samo)


W PHP:

true == 1 (true - wartość równoważna)

true === 1 (false - nie taki sam pod względem wartości i typu)

  • prawda jest logiczna
  • 1 jest int

„=== sprawdza, czy to samo (wartość i typ)”, niezupełnie prawda. Dwa obiekty stdClass mają ten sam typ „obiektu” (tj. Używają gettype ()), ale PHP mówi, że są to dwie różne rzeczy, jeśli używasz ścisłego porównania. Zobacz to .
MAChitgarha

8

Chodzi o typy danych. Weźmy na przykład BOOL(prawda lub fałsz):

truerównież równa się, 1a falsetakże równa się0

==Nie dba o typach danych przy porównywaniu: Więc jeśli miał zmienną, która jest 1 (co może być również true):

$var=1;

A następnie porównaj z ==:

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

Ale $vartak naprawdę nie jest równy true, prawda? 1Zamiast tego ma wartość int , która z kolei jest równa true.

Za ===pomocą typy danych są sprawdzane, aby upewnić się, że dwie zmienne / obiekty / cokolwiek używają tego samego typu.

Więc gdybym to zrobił

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

warunek ten nie byłby spełniony, ponieważ $var !== truejest == true( tylko jeśli wiesz, co mam na myśli).

Dlaczego miałbyś tego potrzebować?

Proste - spójrzmy na jedną z funkcji PHP array_search():

array_search()Funkcja po prostu wyszukuje wartość w tablicy i zwraca kluczowego elementu wartość została znaleziona. Jeśli wartość nie została znaleziona w tablicy, zwraca false . Ale co jeśli zrobiłeś array_search()na wartości zapisanej w pierwszym elemencie tablicy (który miałby klucz tablicy 0) ... array_search()funkcja zwróciłaby 0 ... co jest równe false ...

Więc jeśli zrobiłeś:

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

Czy widzisz, jak może to być teraz problem?

Większość ludzi nie używa == false, sprawdzając, czy funkcja zwraca false. Zamiast tego używają !. Ale w rzeczywistości jest to dokładnie to samo, co używanie ==false, więc jeśli zrobiłeś:

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

W przypadku takich rzeczy należy użyć ===zamiast tego, aby sprawdzić typ danych.


8

Jednym z przykładów jest to, że atrybut bazy danych może mieć wartość NULL lub „”:

$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 == to operator porównania, który porównuje wartość zmiennych. Ale === porównuje wartość i typ danych.

Na przykład,

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

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

W takim przypadku wynikiem będą „Zmienne są równe”, nawet jeśli ich typy danych są różne.

Ale jeśli użyjemy === zamiast ==, wynikiem będzie „Zmienne nie są równe”. PHP najpierw porównuje wartość zmiennej, a następnie typ danych. Tutaj wartości są takie same, ale typy danych są różne.


6

Dany x = 5

1) Operator: == jest „równy”. x == 8jest fałszem
2) Operator: === jest „dokładnie równy” (wartość i typ) x === 5jest prawdą, x === "5"jest fałszem


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

Bądź jednak ostrożny. Oto znany problem.

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

Krótko mówiąc, === działa w taki sam sposób, jak == w większości innych języków programowania.

PHP pozwala na dokonywanie porównań, które tak naprawdę nie mają sensu. Przykład:

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

Chociaż pozwala to na kilka interesujących „skrótów”, powinieneś się wystrzegać, ponieważ funkcja, która zwraca coś, czego nie powinna (np. „Błąd” zamiast liczby), nie zostanie złapana i będziesz zastanawiać się, co się stało.

W PHP == porównuje wartości iw razie potrzeby dokonuje konwersji typu (na przykład ciąg „12343sdfjskfjds” zmieni się na „12343” w porównaniu liczb całkowitych). === porówna wartość ORAZ typ i zwróci false, jeśli typ nie jest taki sam.

Jeśli zajrzysz do instrukcji PHP, zobaczysz, że wiele funkcji zwraca „fałsz”, jeśli funkcja się nie powiedzie, ale mogą zwrócić 0 w udanym scenariuszu, dlatego zalecają wykonanie „if (function ()! == false) ”, aby uniknąć błędów.


1
Należy zauważyć, że oprócz tych „skrótów”, znane jest także nieprawidłowe działanie operatora ==, które otwiera luki bezpieczeństwa, na przykład popularne forum PHP, na którym można ustawić wartość skrótu hasła ciasteczka na true, obchodząc walidacja if (databasehash == cookiehash).
David

3

Kilka przykładów

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

== Porównuje tylko wartość, nie przejmuje się typami danych

vs.

=== Porównuje wartości i typy danych


jaki jest problem z tą odpowiedzią?
Mohit Tanwani

2

Użyłbyś ===, aby sprawdzić, czy funkcja lub zmienna jest fałszem, a nie tylko zrównaniem się z fałszem (zero lub pusty ciąg znaków).

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

W tym przypadku strpos zwróci 0, co w teście będzie równe false

if ($pos == false)

lub

if (!$pos)

co nie jest tym, czego chcesz tutaj.


2

Jeśli chodzi o to, kiedy używać jednego nad drugim, weźmy na przykład fwrite()funkcję w PHP.

Ta funkcja zapisuje zawartość w strumieniu plików. Według PHP „ fwrite()zwraca liczbę zapisanych bajtów lub FAŁSZ w przypadku błędu.”. Jeśli chcesz sprawdzić, czy wywołanie funkcji zakończyło się powodzeniem, ta metoda jest wadliwa:

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

Może zwrócić zero (i jest uważane za udane), a twój stan nadal jest wyzwalany. Właściwy sposób to:

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

2

PHP to luźno napisany język. Użycie operatora podwójnej równości pozwala na swobodne sprawdzanie zmiennej.

Luźne sprawdzenie wartości pozwoliłoby na zrównanie niektórych podobnych, ale nie równych wartości:

  • ''
  • zero
  • fałszywe
  • 0

Wszystkie te wartości byłyby równe za pomocą operatora podwójnej równości.


1

Zmienne mają typ i wartość.

  • $ var = „test” to ciąg znaków, który zawiera „test”
  • $ var2 = 24 to liczba całkowita vhose wynosi 24.

Kiedy używasz tych zmiennych (w PHP), czasami nie masz dobrego typu. Na przykład jeśli tak

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

PHP musi przekonwertować („rzutować”) $ var na liczbę całkowitą. W tym przypadku „$ var == 1” jest prawdziwe, ponieważ każdy niepusty ciąg jest rzutowany na 1.

Używając ===, sprawdzasz, czy wartość I TYP są równe, więc "$ var === 1" jest fałszem.

Jest to przydatne na przykład, gdy masz funkcję, która może zwrócić false (w przypadku błędu) i 0 (wynik):

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

Ten kod jest niepoprawny, jakby myFunction()zwracał 0, jest rzutowany na false i wydaje się, że masz błąd. Prawidłowy kod to:

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

ponieważ test polega na tym, że zwracana wartość „jest wartością logiczną i jest fałszem”, a nie „może być rzutowana na fałsz”.


w odniesieniu do niepustych ciągów, tak naprawdę nie jest to prawdą. „a” == 0 jest PRAWDĄ.
nickf


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

Wszystkie dotychczasowe odpowiedzi ignorują niebezpieczny problem z ===. Na marginesie zauważono, ale nie podkreślono, że liczby całkowite i podwójne są różnymi typami, więc następujący kod:

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

daje:

 equal
 not equal

Zauważ, że NIE jest to przypadek „błędu zaokrąglania”. Dwie liczby są dokładnie równe do ostatniego bitu, ale mają różne typy.

Jest to paskudny problem, ponieważ program używający === może z powodzeniem działać przez lata, jeśli wszystkie liczby są wystarczająco małe (gdzie „wystarczająco małe” zależy od sprzętu i systemu operacyjnego, na którym pracujesz). Jeśli jednak przypadkiem liczba całkowita będzie wystarczająco duża, aby przekształcić ją w podwójną, jej typ zostanie zmieniony „na zawsze”, nawet jeśli kolejna operacja lub wiele operacji może przywrócić jej wartość do małej liczby całkowitej. I jest coraz gorzej. Może się rozprzestrzeniać - infekcja podwójności może być przenoszona na wszystko, czego dotknie, jedno obliczenie na raz.

W prawdziwym świecie może to stanowić problem na przykład w programach obsługujących daty po roku 2038. W tej chwili znaczniki czasu UNIX (liczba sekund od 1970-01-01 00:00:00 UTC) będą wymagały więcej niż 32-bitów, więc ich reprezentacja „magicznie” przełączy się na podwojona w niektórych systemach. Dlatego jeśli obliczysz różnicę dwa razy, możesz skończyć z kilkoma sekundami, ale jako podwójną, a nie liczbą całkowitą, która występuje w 2017 roku.

Myślę, że jest to znacznie gorsze niż konwersje między ciągami i liczbami, ponieważ jest subtelne. Śledzenie tego, co jest ciągiem, a co liczbą, jest dla mnie łatwe, ale śledzenie liczby bitów w liczbie jest poza mną.

Tak więc, w powyższych odpowiedziach jest kilka fajnych tabel, ale nie ma rozróżnienia między 1 (jako liczba całkowita) i 1 (subtelne podwójne) i 1.0 (oczywiste podwójne). Również rada, której powinieneś zawsze używać === i nigdy ==, nie jest świetna, ponieważ === czasami zawiedzie, gdy == działa poprawnie. Również JavaScript nie jest pod tym względem równoważny, ponieważ ma tylko jeden typ liczb (wewnętrznie może mieć różne reprezentacje bitowe, ale nie powoduje problemów dla ===).

Moja rada - nie używaj żadnej. Musisz napisać własną funkcję porównania, aby naprawdę naprawić ten bałagan.


0

Istnieją dwie różnice między nimi == i=== w tablic i obiektów, które moim zdaniem nie wspomnieć tutaj PHP; dwie tablice z różnymi rodzajami kluczy i obiektami.

Dwie tablice z różnymi rodzajami kluczy

Jeśli masz tablicę z sortowaniem według klucza i inną tablicę z innym sortowaniem według klucza, są one całkowicie różne (tzn. Używają === ). Może to spowodować, jeśli posortujesz tablicę kluczem i spróbujesz porównać posortowaną tablicę z oryginalną.

Rozważmy na przykład pustą tablicę. Najpierw próbujemy wypchnąć kilka nowych indeksów do tablicy bez żadnego specjalnego rodzaju. Dobrym przykładem może być tablica z ciągami znaków jako kluczami. Teraz głęboko w przykład:

// Define an array
$arr = [];

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

Teraz mamy tablicę nieposortowanych kluczy (np. „On” pojawił się po „tobie”). Rozważ tę samą tablicę, ale posortowaliśmy jej klucze alfabetycznie:

// Declare array
$alphabetArr = [];

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

Wskazówka : możesz sortować tablicę według klucza za pomocą ksort () .

Teraz masz inną tablicę z innym rodzajem klucza niż pierwszy. Porównamy je:

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

Uwaga : Może to być oczywiste, ale zawsze porównanie dwóch różnych tablic przy użyciu ścisłego porównania false. Jednak dwie dowolne tablice mogą być równe przy użyciu ===lub nie.

Powiedziałbyś: „Ta różnica jest znikoma”. Mówię wtedy, że to różnica, którą należy rozważyć i może się zdarzyć w dowolnym momencie. Jak wspomniano powyżej, sortowanie kluczy w tablicy jest tego dobrym przykładem.

Obiekty

Pamiętaj, że dwa różne obiekty nigdy nie są sobie równe . Te przykłady pomogłyby:

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

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

Uwaga : Przypisanie obiektu do innej zmiennej nie tworzy kopii - tworzy raczej odwołanie do tej samej lokalizacji pamięci co obiekt. Spójrz tutaj .

Uwaga : Od PHP7 dodano anonimowe klasy . Z wyników, nie ma różnicy między new class {}i new stdClass()w testach powyżej.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.