Несоответствие между ИСТИННЫМИ и ЛОЖНЫМИ определениями констант в PHP - PullRequest
2 голосов
/ 03 апреля 2019

Из-за этого иногда я врезаю голову в стену.

var_dump(ord(true), ord(false));

дает:

INT (49)
INT (0)

Таким образом, TRUE преобразуется в код ASCII 49 - номер 1, а FALSE - в код ASCII 0 (нулевой байт). Почему такое несоответствие в преобразованиях ИСТИНА / ЛОЖЬ в строку? Почему ЛОЖЬ не может быть преобразовано в код 48 ASCII - число 0, где ожидается целочисленный контекст (потому что ИСТИНА - «1»)?

Самая большая проблема из таких определений заключается в том, что если вы храните логические значения в некоторых переменных, которые вы позже сохраняете в базе данных - тогда TRUE сохраняется как '1', а FALSE как '' - пустая строка. Поэтому перед сохранением в базе данных вам необходимо привести к целому числу (int)($bool_variable). Учитывая, что PHP поддерживает полностью автоматическое приведение типов, необходимость выполнять ручное приведение типов в некоторых сценариях очень разочаровывает и немного глупа (либо ВСЕ типы должны быть взаимозаменяемыми, либо пользователь должен выполнять приведение между все типы).

Есть идеи?

Ответы [ 3 ]

5 голосов
/ 03 апреля 2019

По своей сути не имеет смысла просить ord из bool. ord ожидает строку, поэтому преобразует любой ввод в строку. true приводит к '1', а false приводит к ''. ord из '1' равно 49, а ord пустой строки равно 0.

Это не значит, что true и false определены как таковые. true определяется как true, а false определяется как false. Это просто правила приведения типов, над которыми вы спотыкаетесь (и да, они, возможно, загадочные) Большинство баз данных поддерживают собственные логические типы, или их API базы данных PHP преобразует логические значения PHP в эквивалент базы данных, если вы правильно используете API.

Что касается , почему существуют такие правила приведения:

Логическое TRUE значение преобразуется в строку "1". Логическое значение FALSE преобразуется в "" (пустая строка). Это позволяет преобразовывать логические и строковые значения туда и обратно.

https://www.php.net/manual/en/language.types.string.php#language.types.string.casting

Нет, это не имеет больше смысла, чем это.

4 голосов
/ 03 апреля 2019

Часть вашего заблуждения в том, что ord - это просто не та функция, которую следует использовать здесь - это не функция приведения и не функция отладки, которая принимает любой тип. Это функция, которая ожидает строку и возвращает int, поэтому PHP должен сначала привести логическое значение к строке, а затем запустить функцию.

Обратите внимание, что PHP не преобразует false в байт NSC ASCII (0). Это всего лишь артефакт того, что вы используете ord() вне его предназначения: вы передали пустую строку и спросили: «Какой первый байт этой строки?» Возможно, он должен был дать вам ошибку, но в этом случае он решил дать вам 0.

Лучшим тестом будет использование var_dump, предназначенное для проверки значений PHP:

var_dump(true); // bool(true)
var_dump(false); // bool(false)
var_dump((string)true); // string(1) "1"
var_dump((string)false); // string(0) ""

Если вы хотите привести логическое значение к выбранному представлению, лучше всего просто использовать троичный оператор:

$bitAsInt = $booleanValue ? 1 : 0;
$bitAsString = $booleanValue ? '1' : '0';
$booleanKeyword = $booleanValue ? 'true' : 'false';
$boolString = $booleanValue ? "'t'" : "'f'";

Все вышеперечисленное подходит для некоторых систем баз данных в некоторых контекстах и ​​служит хорошим объяснением того, почему (string)$booleanValue не может просто дать вам правильную вещь каждый раз.

Существуют и другие сценарии, в которых (string)false предоставление пустой строки является наиболее полезным, и именно это решил PHP. То есть:

(string)$booleanValue === ($booleanValue ? '1' : '')

Всегда есть много ответов на "почему". Для исторического контекста это, вероятно, было вдохновлено Perl (который был популярен для веб-программирования во время создания PHP) - хотя он не имеет логического типа как такового, он демонстрирует похожее поведение приведения:

print ( 1==1 ); # true as string, gives '1'
print ( 1==2 ); # false as string, gives ''
print 0 + ( 1==1 ); # true as int, gives 1
print 0 + ( 1==2 ); # false as int, gives 0
0 голосов
/ 03 апреля 2019

Пустая строка рассматривается php как false.Будь то чтение из базы данных или нет.

Вы пытаетесь решить проблему с запросом к базе данных?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...