ทำไม PHP จึงถือว่า“ 0” เป็น FALSE ในบริบทบูลีน


12

"0" ซึ่งเป็นสตริงที่มีอักขระหนึ่งตัวไม่ใช่สิ่งที่ว่างเปล่าอย่างสังหรณ์ใจ ทำไม PHP จึงถือว่าเป็น FALSE เมื่อถูกแปลงเป็นบูลีนซึ่งแตกต่างจากภาษาการเขียนโปรแกรมอื่น ๆ


2
ซ้ำกับ: stackoverflow.com/questions/523643/… . มันเหมือนกันทั้งใน PHP และจาวาสคริปต์ตรวจสอบคำตอบด้านล่างคำตอบที่ได้รับการยอมรับ
Walfrat

5
เป็นเพราะ PHP มีความพยายามอย่างมากที่จะไม่สอดคล้องกันทั้งกับตัวเองและภาษาการเขียนโปรแกรมอื่น ๆ เท่าที่จะทำได้
David Arno

2
@DavidArno ในทางตรงกันข้ามก็ทำดีที่สุดที่จะสอดคล้องกัน ; เมื่อคุณเริ่มสตริงการ autocasting (มีประโยชน์มากในภาษามักจะคว้า vars จาก URL หรือร้องขอร่างกาย) คุณต้องทำตามตรรกะที่ หาก'0'จะถือว่าเป็น0ใน$x + 1ทำไมไม่ควรก็ยังถือว่าเป็น0และดังนั้นfalseในif ( $x )?
IMSoP

1
@DavidArno อย่างแน่นอน;)
linuxunil

1
@DavidArno เมื่อคุณเริ่มแสดงการปลดเปลื้องความสูญเสียความขัดแย้งบางอย่างหลีกเลี่ยงไม่ได้ฉันคิดว่า; วิธีการแก้ปัญหาที่สอดคล้องกันเกี่ยวข้องกับการปฏิเสธบางปลดเปลื้องและการออกแบบส่วนที่เหลืออย่างระมัดระวัง ภาษาที่ได้รับความนิยมน้อยมากได้รับการออกแบบตั้งแต่เริ่มต้น ส่วนใหญ่วิวัฒนาการมาจากการทดลองที่ได้รับความนิยมโดยบังเอิญหรือจากภาษาเก่าที่มีจุดประสงค์และสัมภาระที่แตกต่างกัน แม้แต่ C # ซึ่งมีการออกแบบเชิงทฤษฎีเสียงจำนวนมากมีมรดกจาก C ซึ่งไม่เคยตั้งใจที่จะเป็นสากลเหมือนที่มันกลายเป็น Snark เช่น "ไปจนถึงความยาวที่ยอดเยี่ยมที่จะไม่สอดคล้องกัน" เป็นเหมือนการตะโกนใส่ผู้ตัดสินที่การแข่งขันกีฬา
IMSoP

คำตอบ:


12

PHP ได้รับการออกแบบ (หรือค่อนข้างพัฒนา) สำหรับใช้กับคำขอของเว็บซึ่งคุณมักจะติดต่อกับอินพุตสตริง (พารามิเตอร์ URL หรือคำขอ POST จากฟอร์มในเบราว์เซอร์) ดังนั้นมันจะส่งสตริงไปยังประเภทอื่นโดยอัตโนมัติ

ตัวอย่างง่ายๆของเรื่องนี้คือการ'1' + '2'ให้3ไม่ใช่ข้อผิดพลาดหรือ'12'หรือการตีความอื่น ๆ ด้วยตรรกะเดียวกันสตริง'0'สามารถใช้เป็นตัวเลข0ได้

ในขณะเดียวกันเช่นหลายภาษา PHP ถือว่าค่าบางอย่างเป็น "เท็จ" เมื่อส่งไปยังบูลีน - คนที่ "ว่างเปล่า" อย่างสังหรณ์ใจตามที่คุณพูด ซึ่งรวมถึงตัวเลข0เช่นเดียวกับสตริงที่ว่างเปล่าและอาร์เรย์ที่ว่างเปล่า'' []ในการifสั่งการแสดงออกอย่างชัดเจนถูกโยนไปบูลจึงเป็นเช่นเดียวกับif ( 0 )if ( false )

เมื่อรวมสองสิ่งนี้เข้าด้วยกันคุณจะได้รับปริศนา: ในแง่หนึ่งอย่างที่คุณบอกว่า'0'เป็นสตริงที่ไม่ว่างเปล่า ในทางกลับกันเราได้กล่าวว่ามันสามารถใช้เป็นตัวเลข0ซึ่งเป็น "ว่าง" PHP เลือกที่จะรักษา "zero-ness" สำคัญกว่า "stringiness" ดังนั้น'0'ถือว่าเป็น "เท็จ"

ในระยะสั้น: '0' == 0 == false; หรือ(bool)'0' === (bool)(int)'0'


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

1
ฉันคิดว่า PHP ใช้สิ่งนี้จาก Perl ซึ่งมี"0" พฤติกรรม“ ผิด” ใน Perl มีความแตกต่างที่ผู้ใช้มองไม่เห็นระหว่างสตริง"0"และหมายเลข0- น่ารำคาญเมื่อจัดการ JSON แต่ใช้งานง่ายมากเมื่อจัดการข้อมูลที่เป็นข้อความ ดังนั้นจึงเป็นไปไม่ได้ที่จะมีตัวเลขที่0เป็นเท็จโดยไม่ต้องมีสตริงที่"0"เป็นเท็จ PHP และ JavaScript ยืมตัดสินใจการออกแบบนี้ แต่เพิ่มความสับสนบางอย่างที่แตกต่างจากสาย / bools / ชนิดของตัวเลขในขณะที่ยังช่วยให้การแปลงโดยปริยาย (PHP: 0 == "0 foo", 0 == falseแต่"0 foo" == true: ==ไม่ได้ transitive)
อมร

@amon ใช่ Perl ใช้วิธีที่น่าสนใจของ (เกือบ) ผู้ประกอบการทั้งหมดและในตัวฟังก์ชั่นการบังคับตัวถูกดำเนินการชนิดโดยเฉพาะอย่างยิ่งกับผู้ประกอบการพิเศษเช่นeqสตริงเท่าเทียมกัน แต่นี้ไม่ได้บันทึกจากที่ไม่ใช่กริยาของปลดเปลื้องสูญเสีย: "0 foo"เป็น truthy ในบริบทแบบบูล แต่จะมีค่าเท่ากับภายใต้0 ==ดังนั้นif ( ! $foo ) ..และ$false = (1 == 2); if ( $foo == $false ) ... อย่าให้ผลลัพธ์เดียวกัน ฉันเดาว่าภาษานั้นไม่มีตัวดำเนินการ "บูลีนเท่าเทียมกัน" ซึ่งสามารถรักษาสิ่งนี้ได้อย่างต่อเนื่อง ...
IMSoP

แม้ว่า "0" จะเป็น 0 เมื่อประเมินเป็นตัวเลข แต่เมื่อเราใช้สตริงในบริบทบูลีน (ตัวอย่างเช่นในคำสั่ง if) เราจะไม่สนใจค่าตัวเลข หากเราต้องการตีความว่าเป็นตัวเลขเราจะเปรียบเทียบกับตัวเลขบางตัวอย่าง$_POST['id'] == 0ซึ่งทำให้เจตนาชัดเจนว่าเราต้องการที่จะปฏิบัติต่อการป้อนข้อมูลของผู้ใช้เป็นตัวเลข
Michael Tsang

1
@MestreLion ตัวอย่างของ Perl ไม่ใช่ PHP ความแตกต่างที่สำคัญคือไม่มีประเภทบูลีนแยกต่างหากใน Perl ดังนั้น$falseตั้งค่าเป็น0; ดังนั้นเมื่อคุณเขียน$foo == $falsePerl ไม่ทราบว่าคุณต้องการการเปรียบเทียบแบบบูลและเปลี่ยนเป็น int แทน ใน PHP นั้นไม่ได้เกิดขึ้นเพราะ$falseเป็นบูลีนเท็จดังนั้นให้==ทำการบูลโดยให้ผลเหมือนกับ!
IMSoP

3

ตามเอกสาร PHP เกี่ยวกับบูลีนมันบอกว่า:

เมื่อแปลงเป็นบูลีนค่าต่อไปนี้จะถือเป็นFALSE
...
สตริงว่างและสตริง "0"
...

มิฉะนั้น:

ค่าอื่น ๆ ทุกค่าจะถือเป็น TRUE (รวมถึงทรัพยากรใด ๆ )

หากคุณทำงาน:

var_dump((bool) "0");

มันจะพิมพ์:

บูล (เท็จ)

ดังนั้นจึงทำงานได้ตามที่คาดไว้


หากต้องการตอบคำถามของคุณอย่างชัดเจน:

อย่างไรก็ตามในกรณีส่วนใหญ่การโยนนั้นไม่จำเป็นเนื่องจากค่าจะถูกแปลงโดยอัตโนมัติหากโอเปอเรเตอร์ฟังก์ชันหรือโครงสร้างการควบคุมต้องการอาร์กิวเมนต์บูลีน

ซึ่งหมายความว่า "autocast" ของ PHP จะแปลง "0" เป็นจำนวนเต็ม 0 ซึ่งอยู่FALSEในโครงสร้างการควบคุมเช่นเขียนif()คำสั่ง


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