Чому PHP трактує "0" як ЛУЖЕ в булевих контекстах?


12

"0", як рядок, що містить один символ, не є чимось інтуїтивно порожнім. Чому PHP трактує це як ЛІЖНЕ, коли перетворюється на булевий, на відміну від інших мов програмування?


2
дублікат: stackoverflow.com/questions/523643 / ... . Це те саме, що і в PHP, і в javascript перевірити відповідь нижче прийнятої відповіді.
Вальфрат

5
Це тому, що PHP намагається бути максимально непослідовним як із самим собою, так і з усіма іншими мовами програмування.
Девід Арно

2
@DavidArno Навпаки, він робить все можливе, щоб бути послідовним ; Після запуску рядків для автоматичного мовлення (дуже зручно мовою, яка часто захоплює варі з 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 вирішує трактувати "нульову" як більш важливу, ніж "суворість", так що '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: ==не транзитивній)
Амон

@amon Так, Perl застосовує цікавий підхід (майже) всіх операторів і вбудованих функцій, що примушують операндів до певного типу, з додатковими операторами, як eqдля рівності рядків. Однак це не рятує його від неперехідності ролі втрат: "0 foo"є тривожним у булевому контексті, але дорівнює 0под ==. Тож if ( ! $foo ) ..і $false = (1 == 2); if ( $foo == $false ) ... не дайте однакового результату. Я думаю, що в мові відсутній оператор "булевої рівності", який би міг ставитись до цього послідовно ...
IMSoP

Хоча "0" дорівнює 0, коли оцінюється як числовий, коли ми використовуємо рядок у булевому контексті (наприклад, у операторі if), нас не цікавить його числове значення. Якщо ми хочемо інтерпретувати його як числовий, ми б порівняли його з деяким числом, наприклад $_POST['id'] == 0, що дає зрозуміти, що ми хочемо трактувати введення користувача як число.
Майкл Цанг

1
@MestreLion Цей приклад був перлом, а не PHP. Найважливішою відмінністю є те, що в Perl не існує окремого булевого типу, тому в $falseкінцевому підсумку встановлено 0: тож коли ви пишете $foo == $false, Perl не знає, що ви хочете логічного порівняння, і замість цього він робить інт. У PHP цього не відбувається, тому що $falseбулева ==!
помилка

3

Згідно з документацією PHP про булеві , там сказано:

При перетворенні в булеві значення вважаються наступними значеннями FALSE
...
порожнім рядком та рядком "0"
...

Інакше:

Кожне інше значення вважається ПРАВИЛЬНИМ (включаючи будь-який ресурс).

Якщо ви запускаєте:

var_dump((bool) "0");

Він надрукує:

bool (помилково)

Так це працює, як очікувалося.


Щоб чітко відповісти на ваше запитання:

Однак у більшості випадків подання є непотрібним, оскільки значення буде автоматично перетворено, якщо оператор, функція або керуюча структура потребують булевого аргументу.

Це означає, що "автокаст" PHP приведе "0" до цілого числа 0, що також є FALSEв керуючій структурі, як, наприклад, if()заява.


Мені хотілося б знати обґрунтування дизайнерського рішення, яке трактує "0" як ЛІЖНЕ при перетворенні на булеве, а не необхідність явного кастингу.
Майкл Цанг
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.