ตัวดำเนินการเปรียบเทียบความเท่าเทียมกันของ PHP (== สองเท่า) และตัวตน (=== สามเท่า) แตกต่างกันอย่างไร


509

ความแตกต่างระหว่าง==และ===คืออะไร?

  • การ==เปรียบเทียบแบบหลวม ๆทำงานอย่างไร
  • การ===เปรียบเทียบที่เข้มงวดทำงานอย่างไร

อะไรคือตัวอย่างที่มีประโยชน์

คำตอบ:


633

ความแตกต่างระหว่าง==และ===

ความแตกต่างระหว่าง==โอเปอเรเตอร์ที่เท่ากันอย่างหลวมและโอเปอเรเตอร์ที่===เหมือนกันอย่างเข้มงวดถูกอธิบายไว้ในคู่มือ :

ผู้ประกอบการเปรียบเทียบ

┌──────────┬───────────┬────────────────────────── ─────────────────────────────────┐
│ตัวอย่าง│ชื่อ│ผลลัพธ์│
├──────────┼───────────┼────────────────────────── ─────────────────────────────────┤
│ $ a == $ b │เท่ากับ│ TRUE หาก $ a เท่ากับ $ b หลังจากเล่นกลแบบ │
│ $ a === $ b │เหมือนกัน│ TRUE ถ้า $ a เท่ากับ $ b และเป็นประเภทเดียวกัน │
└──────────┴───────────┴────────────────────────── ─────────────────────────────────┘

==เปรียบเทียบกันอย่างหลวม ๆ

หากคุณกำลังใช้==ประกอบการหรือดำเนินการเปรียบเทียบอื่น ๆ ซึ่งใช้กันอย่างหลวม ๆ เปรียบเทียบเช่น!=, <>หรือ==คุณมักจะมีไปดูที่บริบทที่จะเห็นสิ่งที่และทำไมบางสิ่งบางอย่างได้รับการแปลงที่จะเข้าใจสิ่งที่เกิดขึ้น

การแปลงกฎ

พิมพ์ตารางเปรียบเทียบ

เป็นข้อมูลอ้างอิงและตัวอย่างคุณสามารถดูตารางเปรียบเทียบในคู่มือ :

เปรียบเทียบกับ ==

┌─────────┬───────┬───────┬───────┬───────┬─────── ┬───────┬───────┬───────┬───────┬─────────┬─────── ┬───────┐
││ TRUE │ FALSE │ 1 │ 0 │ -1 │ "1" │ "0" │ "0" -1 "│อาร์เรย์ NULL │ () ph" php "│" "│
├─────────┼───────┼───────┼───────┼───────┼─────── ┼───────┼───────┼───────┼───────┼─────────┼─────── ┼───────┤
│ TRUE │ TRUE │ FALSE │ TRUE AL FALSE │ TRUE │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │
AL FALSE │ FALSE │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ TRUE │ TRUE │ FALSE │ TRUE │
│ 1 │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │
│ 0 │ FALSE │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ TRUE │ FALSE │ TRUE │ TRUE │
│ -1 │ TRUE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │
│ "1" │ TRUE │ FALSE │ TRUE AL FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │
│ "0" AL FALSE │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │
│ "-1" │ TRUE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │
ULL NULL │ FALSE │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ TRUE │ FALSE │ TRUE │
│ array () │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ TRAL │ FALSE │ FALSE │
│ "php" │ TRUE │ FALSE │ FALSE │ TRAL │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │
│ "" │ FALSE │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE AL FALSE │ FALSE │ TRUE │
└─────────┴───────┴───────┴───────┴───────┴─────── ┴───────┴───────┴───────┴───────┴─────────┴─────── ┴───────┘

===การเปรียบเทียบที่เหมือนกันอย่างเข้มงวด

หากคุณกำลังใช้===โอเปอเรเตอร์หรือโอเปอเรเตอร์การเปรียบเทียบอื่น ๆ ที่ใช้การเปรียบเทียบอย่างเข้มงวดเช่น!==หรือ===จากนั้นคุณสามารถมั่นใจได้ว่าประเภทจะไม่เปลี่ยนแปลงอย่างน่าอัศจรรย์เพราะจะไม่มีการแปลงเกิดขึ้น ดังนั้นด้วยการเปรียบเทียบอย่างเข้มงวดชนิดและค่าจะต้องเหมือนกันไม่ใช่เฉพาะค่า

พิมพ์ตารางเปรียบเทียบ

เป็นข้อมูลอ้างอิงและตัวอย่างคุณสามารถดูตารางเปรียบเทียบในคู่มือ :

การเปรียบเทียบที่เข้มงวดกับ ===

┌─────────┬───────┬───────┬───────┬───────┬─────── ┬───────┬───────┬───────┬───────┬─────────┬─────── ┬───────┐
││ TRUE │ FALSE │ 1 │ 0 │ -1 │ "1" │ "0" │ "0" -1 "│อาร์เรย์ NULL │ () ph" php "│" "│
├─────────┼───────┼───────┼───────┼───────┼─────── ┼───────┼───────┼───────┼───────┼─────────┼─────── ┼───────┤
│ TRUE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │
AL FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │
│ 1 │ FALSE │ FALSE │ TRAL │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │
│ 0 │ FALSE │ FALSE │ FALSE │ TRAL │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │
│ -1 │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │
│ "1" AL FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │
│ "0" AL FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │
│ "-1" AL FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │
ULL NULL │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │
│ array () │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRAL │ FALSE │ FALSE │
ph "php" │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRAL │ FALSE │
│ "" │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRAL │
└─────────┴───────┴───────┴───────┴───────┴─────── ┴───────┴───────┴───────┴───────┴─────────┴─────── ┴───────┘

65
ไม่มีใครคิดว่าแปลกที่ "000" == "0000"
nickf

36
สิ่งที่ทำให้ฉันประหลาดใจอยู่เสมอคือ false == array () และ false == 0 แต่ array ()! = 0 ดังนั้น false == array ()! = / == 0? ที่รู้สึกแปลกสำหรับฉัน
Pim Jager

4
@Pim ... ต่อ: ดูว่าวิธีนี้ส่งไปยังบูลมีค่าใด ๆ เท่านั้นที่มีการตกอยู่ในหนึ่งในสองด้านหรือtrue falseมันง่ายที่จะร่าย แม้ว่าจะมีค่าอื่น ๆ ทั้งหมดสำหรับการใช้งานจริงทั้งหมดรวมกันได้ไม่ จำกัด คือ"five" == 5อะไร array(0) == 0? array(0,0,0) == 0? 0.0000000000000000000000000000000000000000000000000001 == array()?
หลอกลวง

12
@Raithlin ระวังอาร์เรย์ เท่ากับสามให้falseสำหรับอาร์เรย์ที่แตกต่างกันใน JavaScript แต่trueสำหรับ PHP ตราบใดที่ค่าของพวกเขามีความเท่าเทียมกัน
Pacerier

14
@Rathlin, gotchas อื่น ๆ อีกมากมาย ใน JavaScript: "000" != "00" , "000" == null, "000" == false, "0x0" == false, array() == 0, false != null, array() != null, ,false == "0x0" ใน PHP มันเป็นพฤติกรรมที่ตรงข้าม: , , , , , , , , false == "000" "000" == "00""000" != null"000" != false"0x0" != falsearray() != 0false == nullarray() == nullfalse != "0x0"false != "000"
Pacerier

239

ผู้ประกอบการ == ปลดเปลื้องระหว่างสองประเภทที่แตกต่างกันหากพวกเขาจะแตกต่างกันในขณะที่ผู้ประกอบการ === ดำเนินการ 'การเปรียบเทียบ typesafe' นั่นหมายความว่ามันจะคืนค่าจริงถ้าตัวถูกดำเนินการทั้งสองมีประเภทเดียวกันและมีค่าเท่ากัน

ตัวอย่าง:

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

คำเตือน : สองอินสแตนซ์ของคลาสเดียวกันกับสมาชิกที่เทียบเท่าไม่ตรงกับ===โอเปอเรเตอร์ ตัวอย่าง:

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

3
nitpick: === จะกลับจริงถ้าทั้งสองตัวถูกดำเนินการเป็นประเภทเดียวกันและค่านิยมที่มีค่าเท่ากัน =)
gnud

1
@gnud นั่นคือสิ่งที่เขาแสดงในตัวอย่าง หากเป็นการเปรียบเทียบประเภทมันจะถูกเรียกว่า "การเปรียบเทียบประเภท" ไม่ได้
Rob Stevenson-Leggett

3
หลังจากใช้ PHP เป็นเวลา 8 ปีเมื่อวานเป็นครั้งแรกที่ฉันถูกจับในสถานการณ์ที่ฉันควรใช้ ===

3
=== จริงถ้าพวกเขาเท่ากันและมีประเภทเดียวกัน == จริงถ้าพวกเขาเท่ากัน ! = จริงหากพวกเขาไม่เท่ากัน ! == จริงถ้าทั้งคู่ไม่เท่ากันหรือเท่ากัน แต่ไม่ใช่ประเภทเดียวกัน
Jeremy C

1
นอกจากนี้การใช้ === ก็เร็วกว่า == เล็กน้อยเนื่องจากไม่จำเป็นต้องแปลงค่าก่อนที่จะตรวจสอบว่ามีค่าเท่ากันหรือไม่
clauziere

88

ภาพที่มีค่าพันคำ:

PHP Double Equals ==เท่าเทียมกันแผนภูมิ:

ป้อนคำอธิบายรูปภาพที่นี่

PHP Triple Equals Equals ===chart:

ป้อนคำอธิบายรูปภาพที่นี่

ซอร์สโค้ดเพื่อสร้างภาพเหล่านี้:

https://github.com/sentientmachine/php_equality_charts

การทำสมาธิของปราชญ์

ผู้ที่ต้องการรักษาสติไม่อ่านเพิ่มเติมเพราะไม่มีสิ่งนี้จะทำให้รู้สึกใด ๆ ยกเว้นที่จะบอกว่านี่เป็นวิธีที่ PHP เศษเล็กเศษน้อยที่ได้รับการออกแบบ

  1. NAN != NAN แต่ NAN == trueแต่
  2. ==จะแปลงตัวถูกดำเนินการซ้ายและขวาให้เป็นตัวเลขหากเหลือเป็นตัวเลข ดังนั้น123 == "123foo"แต่"123" != "123foo"
  3. สตริงเลขฐานสิบหกในเครื่องหมายคำพูดเป็นลอยในบางครั้งและจะถูกโยนแปลกใจที่จะลอยกับความประสงค์ของคุณทำให้เกิดข้อผิดพลาดรันไทม์

  4. ==ไม่ได้เพราะสกรรมกริยา"0"== 0และ0 == ""แต่"0" != ""

  5. PHP ตัวแปรที่ยังไม่ได้รับการประกาศให้เป็นเท็จเลยแม้ว่า PHP ==มีวิธีที่จะเป็นตัวแทนของตัวแปรที่ไม่ได้กำหนดเป็นคุณลักษณะที่ถูกปิดใช้งานด้วย
  6. "6" == " 6", "4.2" == "4.20"และแต่"133" == "0133" 133 != 0133แต่"0x10" == "16"และ"1e3" == "1000"การเปิดเผยว่าการแปลงสตริงของเซอร์ไพรส์เป็นฐานแปดจะเกิดขึ้นทั้งคู่โดยที่คุณไม่ได้รับคำแนะนำหรือยินยอมทำให้เกิดข้อผิดพลาดรันไทม์

  7. False == 0, "", []และ"0"และ

  8. เมื่อตัวเลขมีขนาดใหญ่พอจะมีค่าเป็น == Infinity

  9. คลาสใหม่คือ == ถึง 1

  10. False เป็นค่าที่อันตรายที่สุดเนื่องจาก False คือ == ตัวแปรอื่น ๆ ส่วนใหญ่การเอาชนะวัตถุประสงค์นั้น

ความหวัง:

หากคุณใช้ PHP คุณจะไม่ใช้ตัวดำเนินการเท่ากับสองเท่าเพราะถ้าคุณใช้สามเท่ากับกรณีขอบเดียวที่ต้องกังวลคือ NAN และตัวเลขใกล้เคียงกับอนันต์ที่พวกเขาจะไม่มีที่สิ้นสุด ด้วยการเท่ากับสองเท่าสิ่งใดก็ตามที่สามารถสร้างความประหลาดใจ==ให้กับทุกสิ่งหรือหรือสามารถสร้างความประหลาดใจเมื่อเทียบกับความต้องการของคุณและ!=สิ่งที่ควรจะเท่ากันอย่างเห็นได้ชัด

ทุกที่ที่คุณใช้==ใน PHP นั้นเป็นโค้ดที่ไม่ดีเพราะมีบั๊ก 85 ตัวที่ถูกเปิดเผยโดยกฎการส่งข้อมูลโดยปริยาย


เป็นความคิดที่ดีจริงๆหรือที่จะรักษาความปลอดภัยให้ใช้เลขสามตัวเสมอ
Chazy Chaz

3
ใช่คุณสมบัติถ่ายทอดของสามเท่ากับทำให้มีความปลอดภัยและหน้าเว็บมากขึ้น
Eric Leschinski

ตัวเลขจะใกล้เคียงกับอนันต์อย่างไร? [ระเบิดสมอง gif]
ทิม

40

เกี่ยวกับ JavaScript:

ตัวดำเนินการ === ทำงานเหมือนกับตัวดำเนินการ == แต่ต้องการให้ตัวถูกดำเนินการนั้นไม่เพียง แต่มีค่าเท่ากัน แต่ยังเป็นชนิดข้อมูลเดียวกัน

ตัวอย่างเช่นตัวอย่างด้านล่างจะแสดง 'x และ y เท่ากัน' แต่ไม่ใช่ 'x และ y เท่ากัน'

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

เพิ่มขึ้นเช่นนี้ดูเหมือนว่าจะเป็นสถานการณ์เดียวกันสำหรับ php
David กล่าวว่าคืนสถานะโมนิก้า

1
@DavidThomas มันไม่เหมือนกันเลยดูstackoverflow.com/questions/12598407/…
xdazz

22

นอกเหนือจากคำตอบอื่น ๆ ที่เกี่ยวข้องกับการเปรียบเทียบวัตถุ:

== เปรียบเทียบวัตถุโดยใช้ชื่อของวัตถุและค่าของพวกเขา หากวัตถุสองชนิดเป็นชนิดเดียวกันและมีค่าสมาชิกเหมือนกัน$a == $bจะให้ผลเป็นจริง

=== เปรียบเทียบ id วัตถุภายในของวัตถุ แม้ว่าสมาชิกจะเท่ากัน$a !== $bถ้าพวกเขาไม่ใช่วัตถุเดียวกัน

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

ในแง่ง่ายที่สุด:

== ตรวจสอบว่าเทียบเท่า (ค่าเท่านั้น)

=== ตรวจสอบว่าเหมือนกัน (ค่า && ประเภท)


เทียบเท่ากับเดียวกัน: การเปรียบเทียบ

1 + 1 = 2 + 0 (เทียบเท่า)

1 + 1 = 1 + 1 (เหมือนกัน)


ใน PHP:

true == 1 (จริง - เทียบเท่ามูลค่า)

true === 1 (เท็จ - ไม่เหมือนกันในค่า && ประเภท)

  • true เป็นบูลีน
  • 1 คือint

"=== ตรวจสอบว่าเหมือนกัน (ค่า && ประเภท)" ไม่จริงทั้งหมด สองวัตถุ stdClass มี 'วัตถุ' ชนิดเดียวกัน (เช่นใช้ gettype ()) แต่ PHP บอกว่าพวกเขาเป็นสองสิ่งที่แตกต่างกันถ้าคุณใช้การเปรียบเทียบที่เข้มงวด ดูนี่สิ
MAChitgarha

8

มันคือทั้งหมดที่เกี่ยวกับประเภทข้อมูล ยกตัวอย่างBOOL(จริงหรือเท็จ):

trueยังเท่ากับ1และ falseเท่ากับ0

==ไม่สนใจเกี่ยวกับชนิดข้อมูลเมื่อเปรียบเทียบ: ดังนั้นถ้าคุณมีตัวแปรที่ 1 (ซึ่งอาจจะเป็นtrue):

$var=1;

แล้วเปรียบเทียบกับ==:

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

แต่$varไม่เท่ากันจริงtrueเหรอ? มันมีค่า int 1แทนซึ่งจะเท่ากับจริง

ด้วย===ชนิดข้อมูลจะถูกตรวจสอบเพื่อให้แน่ใจว่าทั้งสองตัวแปร / วัตถุ / สิ่งที่ใช้ชนิดเดียวกัน

ดังนั้นถ้าฉันทำ

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

เงื่อนไขนั้นจะไม่เป็นจริงตาม$var !== trueนั้นเท่านั้น== true(ถ้าคุณรู้ว่าฉันหมายถึงอะไร)

ทำไมคุณต้องการสิ่งนี้

ง่าย - ลองมาดูหนึ่งในฟังก์ชั่นของ PHP array_search():

array_search()ฟังก์ชั่นการค้นหาเพียงสำหรับค่าในอาร์เรย์และผลตอบแทนที่สำคัญขององค์ประกอบค่าที่ถูกพบใน. ถ้าค่าไม่พบในอาร์เรย์ก็จะส่งกลับเท็จ แต่ถ้าคุณทำarray_search()ตามค่าที่เก็บไว้ในองค์ประกอบแรกของอาร์เรย์ (ซึ่งจะมีคีย์อาร์เรย์ของ0) ....array_search()ฟังก์ชั่นจะกลับ 0 ... ซึ่งเท่ากับเท็จ ..

ดังนั้นถ้าคุณทำ:

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

ดังนั้นคุณเห็นว่าสิ่งนี้อาจเป็นปัญหาได้หรือไม่

คนส่วนใหญ่ไม่ใช้== falseเมื่อตรวจสอบว่าฟังก์ชันส่งกลับค่าเท็จหรือไม่ !แต่พวกเขาใช้ แต่จริงๆแล้วมันเหมือนกับการใช้==falseดังนั้นถ้าคุณทำ:

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

ดังนั้นสำหรับสิ่งต่าง ๆ เช่นนั้นคุณจะใช้===แทนเพื่อให้มีการตรวจสอบชนิดข้อมูล


8

ตัวอย่างหนึ่งคือแอ็ตทริบิวต์ฐานข้อมูลอาจเป็นโมฆะหรือ "":

$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 == เป็นตัวดำเนินการเปรียบเทียบซึ่งเปรียบเทียบค่าของตัวแปร แต่ === เปรียบเทียบค่าและชนิดข้อมูล

ตัวอย่างเช่น,

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

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

ในกรณีนี้ผลลัพธ์จะเป็น 'ตัวแปรเท่ากัน' แม้ว่าประเภทข้อมูลจะแตกต่างกัน

แต่ถ้าเราใช้ === แทนที่จะเป็น == ผลลัพธ์จะเป็น 'ตัวแปรไม่เท่ากัน' php ก่อนจะเปรียบเทียบค่าของตัวแปรจากนั้นชนิดข้อมูล ที่นี่ค่าเหมือนกัน แต่ชนิดข้อมูลแตกต่างกัน


6

ป.ร. ให้ไว้ x = 5

1) ผู้ประกอบการ: == คือ "เท่ากับ" x == 8เป็นเท็จ
2) ผู้ประกอบการ: === คือ "เท่ากับเท่ากับ" (ค่าและประเภท) x === 5เป็นจริงx === "5"เป็นเท็จ


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

ระวังให้ดี นี่คือปัญหาที่มีชื่อเสียง

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

เมื่อเทียบกับ

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

3

ในระยะสั้น === ทำงานในลักษณะเดียวกับที่ == ทำในภาษาการเขียนโปรแกรมอื่นส่วนใหญ่

PHP ช่วยให้คุณทำการเปรียบเทียบที่ไม่สมเหตุสมผล ตัวอย่าง:

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

ขณะที่สิ่งนี้อนุญาตให้ "ทางลัด" ที่น่าสนใจบางอย่างคุณควรระวังเนื่องจากฟังก์ชั่นที่คืนสิ่งที่ไม่ควร (เช่น "ข้อผิดพลาด" แทนที่จะเป็นตัวเลข) จะไม่ถูกจับได้และคุณจะสงสัยว่าเกิดอะไรขึ้น

ใน PHP == เปรียบเทียบค่าและทำการแปลงประเภทหากจำเป็น (ตัวอย่างเช่นสตริง "12343sdfjskfjds" จะกลายเป็น "12343" ในการเปรียบเทียบจำนวนเต็ม) === จะเปรียบเทียบค่าและชนิดและจะส่งคืนค่าเท็จหากชนิดไม่เหมือนกัน

หากคุณดูในคู่มือ PHP คุณจะเห็นว่าฟังก์ชันจำนวนมากส่งคืน "false" หากฟังก์ชันล้มเหลว แต่อาจส่งคืน 0 ในสถานการณ์ที่ประสบความสำเร็จซึ่งเป็นสาเหตุที่พวกเขาแนะนำให้ทำ "if (function ()! == false) "เพื่อหลีกเลี่ยงข้อผิดพลาด


1
ควรสังเกตว่านอกเหนือจาก "ทางลัด" เหล่านั้นพฤติกรรมที่ผิดปกติของผู้ประกอบการ == ได้รับการรู้จักในการเปิดช่องโหว่ด้านความปลอดภัยตัวอย่างเช่นฟอรัม PHP ยอดนิยมที่เป็นไปได้ที่จะตั้งค่าแฮชรหัสผ่านคุกกี้เป็นจริง การตรวจสอบ if (databasehash == cookiehash)
David

3

ไม่กี่ตัวอย่าง

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

== เปรียบเทียบค่าเท่านั้นมันจะไม่รบกวนเกี่ยวกับประเภทข้อมูล

เมื่อเทียบกับ

=== เปรียบเทียบค่าและชนิดข้อมูล


ปัญหาของคำตอบนี้คืออะไร
Mohit Tanwani

2

คุณจะใช้ === เพื่อทดสอบว่าฟังก์ชั่นหรือตัวแปรเป็นเท็จมากกว่าเพียงแค่เท่ากับเป็นเท็จ (ศูนย์หรือสตริงว่าง)

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

ในกรณีนี้ strpos จะคืนค่า 0 ซึ่งจะถือว่าเป็นเท็จในการทดสอบ

if ($pos == false)

หรือ

if (!$pos)

ซึ่งไม่ใช่สิ่งที่คุณต้องการที่นี่


2

สำหรับเมื่อจะใช้อย่างใดอย่างหนึ่งใช้ตัวอย่างfwrite()ฟังก์ชั่นใน PHP

ฟังก์ชั่นนี้เขียนเนื้อหาไปยังสตรีมไฟล์ ตาม PHP, " fwrite()ส่งคืนจำนวนไบต์ที่เขียน, หรือ FALSE เนื่องจากข้อผิดพลาด" หากคุณต้องการทดสอบว่าการเรียกใช้ฟังก์ชันสำเร็จหรือไม่วิธีนี้จะมีข้อบกพร่อง:

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

มันสามารถกลับเป็นศูนย์ (และถือว่าประสบความสำเร็จ) และสภาพของคุณยังคงได้รับการเรียก วิธีที่ถูกต้องคือ:

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

2

PHP เป็นภาษาที่พิมพ์อย่างหลวม ๆ การใช้ตัวดำเนินการเท่ากันสองเท่าช่วยให้สามารถตรวจสอบตัวแปรได้อย่างหลวม ๆ

การตรวจสอบค่าที่หลวมจะช่วยให้ค่าที่คล้ายกัน แต่ไม่เท่ากันมีค่าเท่ากัน:

  • ''
  • โมฆะ
  • เท็จ
  • 0

ค่าเหล่านี้ทั้งหมดจะเท่ากันโดยใช้ตัวดำเนินการเท่ากับสองเท่า


1

ตัวแปรมีชนิดและค่า

  • $ var = "test" เป็นสตริงที่มี "test"
  • $ var2 = 24 เป็นค่า vhose จำนวนเต็มคือ 24

เมื่อคุณใช้ตัวแปรเหล่านี้ (เป็น PHP) บางครั้งคุณอาจมีประเภทที่ไม่ดี ตัวอย่างเช่นถ้าคุณทำ

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

PHP ต้องแปลง ("to cast") $ var เป็นจำนวนเต็ม ในกรณีนี้ "$ var == 1" เป็นจริงเพราะสตริงที่ไม่ว่างจะถูกส่งไปที่ 1

เมื่อใช้ === คุณตรวจสอบว่าค่าและประเภทเท่ากันดังนั้น "$ var === 1" จึงเป็นเท็จ

สิ่งนี้มีประโยชน์ตัวอย่างเช่นเมื่อคุณมีฟังก์ชั่นที่สามารถคืนค่าเท็จ (เมื่อเกิดข้อผิดพลาด) และ 0 (ผลลัพธ์):

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

รหัสนี้ผิดเหมือนmyFunction()คืน 0 มันถูกโยนเป็นเท็จและคุณดูเหมือนจะมีข้อผิดพลาด รหัสที่ถูกต้องคือ:

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

เพราะการทดสอบคือค่าตอบแทน "เป็นบูลีนและเป็นเท็จ" และไม่ใช่ "สามารถแปลงเป็นเท็จ"


เกี่ยวกับสตริงที่ไม่ว่างเปล่านั่นจริงไม่จริง "a" == 0 คือ TRUE
nickf

1

===ผู้ประกอบการควรจะเปรียบเทียบแน่นอนความเสมอภาคเนื้อหาในขณะที่==ผู้ประกอบการจะเปรียบเทียบความหมายของความเท่าเทียมกัน โดยเฉพาะอย่างยิ่งมันจะบีบบังคับสตริงให้กับตัวเลข

ความเท่าเทียมกันเป็นเรื่องที่กว้างขวาง ดูบทความวิกิพีเดียเท่าเทียมกัน


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

คำตอบทั้งหมดไม่สนใจปัญหาที่เป็นอันตรายด้วย === มันได้รับการบันทึกในการผ่าน แต่ไม่เน้นว่าจำนวนเต็มและสองครั้งนั้นเป็นประเภทที่แตกต่างกันดังนั้นรหัสต่อไปนี้:

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

ให้:

 equal
 not equal

โปรดทราบว่านี่ไม่ใช่กรณีของ "ข้อผิดพลาดในการปัดเศษ" ตัวเลขสองตัวนั้นเท่ากันจนถึงบิตสุดท้าย แต่มีชนิดต่างกัน

นี่เป็นปัญหาที่น่ารังเกียจเพราะโปรแกรมที่ใช้ === สามารถทำงานได้อย่างมีความสุขเป็นเวลาหลายปีหากตัวเลขทั้งหมดมีขนาดเล็กพอ (โดยที่ "เล็กพอ" ขึ้นอยู่กับฮาร์ดแวร์และระบบปฏิบัติการที่คุณใช้งาน) อย่างไรก็ตามถ้าบังเอิญมีจำนวนเต็มที่มากพอที่จะแปลงเป็นสองเท่าชนิดของมันจะถูกเปลี่ยนเป็น "ถาวร" แม้ว่าการดำเนินการที่ตามมาหรือการดำเนินงานจำนวนมากอาจนำกลับไปเป็นค่าจำนวนเต็มเล็กน้อย และมันแย่ลงเรื่อย ๆ มันสามารถแพร่กระจาย - การติดเชื้อสองครั้งสามารถส่งผ่านไปยังสิ่งที่มันสัมผัสการคำนวณครั้งละหนึ่ง

ในโลกแห่งความเป็นจริงสิ่งนี้น่าจะเป็นปัญหาในโปรแกรมที่จัดการกับวันที่เกินปี 2581 เป็นต้น ในเวลานี้การประทับเวลา UNIX (จำนวนวินาทีตั้งแต่ 1970-01-01 00:00:00 UTC) จะต้องใช้มากกว่า 32 บิตดังนั้นการแสดงจะเปลี่ยนเป็น "วิเศษ" เพื่อเพิ่มเป็นสองเท่าในบางระบบ ดังนั้นหากคุณคำนวณความแตกต่างระหว่างสองครั้งคุณอาจสิ้นสุดด้วยสองสามวินาที แต่เป็นสองเท่าแทนที่จะเป็นผลลัพธ์จำนวนเต็มที่เกิดขึ้นในปี 2560

ฉันคิดว่ามันแย่กว่าการแปลงระหว่างสตริงและตัวเลขเพราะมันบอบบาง ฉันคิดว่ามันง่ายในการติดตามว่าสตริงคืออะไรและอะไรคือตัวเลข แต่การติดตามจำนวนบิตในจำนวนนั้นเกินกว่าฉัน

ดังนั้นในคำตอบข้างต้นมีบางตารางที่ดี แต่ไม่มีความแตกต่างระหว่าง 1 (เป็นจำนวนเต็ม) และ 1 (บอบบางเล็กน้อย) และ 1.0 (ชัดเจนสองครั้ง) นอกจากนี้คำแนะนำที่คุณควรใช้เสมอ === และไม่เคย == ไม่ดีเพราะบางครั้ง === จะล้มเหลวโดยที่ == ทำงานได้อย่างถูกต้อง นอกจากนี้จาวาสคริปต์ยังไม่เทียบเท่าในเรื่องนี้เพราะมันมีประเภทตัวเลขเพียงหมายเลขเดียว (ภายในอาจมีการแทนค่าบิตที่ชาญฉลาดแตกต่างกัน แต่ก็ไม่ได้ทำให้เกิดปัญหา ===)

คำแนะนำของฉัน - ไม่ใช้ คุณต้องเขียนฟังก์ชันเปรียบเทียบของคุณเองเพื่อแก้ไขระเบียบนี้


0

มีสองความแตกต่างระหว่าง==และ===ใน PHP อาร์เรย์และวัตถุที่ฉันคิดว่าไม่ได้พูดถึงที่นี่; สองอาร์เรย์ที่มีการเรียงลำดับคีย์ที่แตกต่างกันและวัตถุ

สองอาร์เรย์ที่มีการเรียงลำดับคีย์ที่แตกต่างกัน

หากคุณมีอาเรย์ที่มีการเรียงลำดับคีย์และอาเรย์อื่นที่มีการเรียงลำดับคีย์ที่แตกต่างกันจะมีความแตกต่างอย่างเคร่งครัด (เช่นการใช้===) ซึ่งอาจทำให้เกิดถ้าคุณทำการเรียงลำดับคีย์และลองเปรียบเทียบอาเรย์ที่เรียงกับแบบดั้งเดิม

ตัวอย่างเช่นพิจารณาอาร์เรย์ว่าง อันดับแรกเราพยายามที่จะส่งดัชนีใหม่ไปยังอาร์เรย์โดยไม่มีการเรียงลำดับพิเศษ ตัวอย่างที่ดีคืออาร์เรย์ที่มีสตริงเป็นกุญแจ ตอนนี้ลึกเข้าไปในตัวอย่าง:

// Define an array
$arr = [];

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

ตอนนี้เรามีอาร์เรย์ที่ไม่เรียงลำดับคีย์ (เช่น 'เขา' มาหลังจาก 'คุณ') พิจารณาอาร์เรย์เดียวกัน แต่เราเรียงลำดับคีย์ตามตัวอักษร:

// Declare array
$alphabetArr = [];

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

ปลาย : คุณสามารถเรียงลำดับอาร์เรย์โดยคีย์โดยใช้ksort ()ฟังก์ชั่น

ตอนนี้คุณมีอาร์เรย์อื่นที่มีการเรียงลำดับคีย์ที่แตกต่างจากอันแรก ดังนั้นเราจะเปรียบเทียบพวกเขา:

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

หมายเหตุ : มันอาจจะชัดเจน แต่การเปรียบเทียบทั้งสองแตกต่างกันfalseอาร์เรย์การเปรียบเทียบการใช้อย่างเคร่งครัดเสมอผล อย่างไรก็ตามสองอาร์เรย์โดยพลการอาจจะเท่ากันโดยใช้===หรือไม่

คุณจะพูดว่า: "ความแตกต่างนี้เล็กน้อย" จากนั้นฉันก็บอกว่ามันเป็นความแตกต่างและควรได้รับการพิจารณาและอาจเกิดขึ้นได้ทุกเวลา ดังกล่าวข้างต้นการเรียงลำดับคีย์ในอาร์เรย์เป็นตัวอย่างที่ดีของสิ่งนั้น

วัตถุ

เก็บไว้ในใจสองวัตถุที่แตกต่างกันจะไม่เข้มงวดเท่ากัน ตัวอย่างเหล่านี้จะช่วย:

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

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

หมายเหตุ : การกำหนดวัตถุให้กับตัวแปรอื่นจะไม่สร้างสำเนา แต่เป็นการสร้างการอ้างอิงไปยังตำแหน่งหน่วยความจำเดียวกับวัตถุ ดูที่นี่

หมายเหตุ : ตั้งแต่ PHP7 จะมีการเพิ่มคลาสที่ไม่ระบุชื่อ จากผลลัพธ์ไม่มีความแตกต่างระหว่างnew class {}และnew stdClass()ในการทดสอบข้างต้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.