У меня есть следующий код:
$item['price'] = 0; /*code to get item information goes in here*/ if($item['price'] == 'e') { $item['price'] = -1; }
Он предназначен для инициализации цены товара до 0, а затем получения информации об этом. Если цена указана как «е», это означает обмен вместо продажи, который обозначается отрицательным значением, поскольку он должен храниться в базе данных, которая требует числового значения.
Существует также возможность оставить цену как 0, либо потому, что товар является бонусом, либо потому, что цена будет установлена в более поздний момент.
Но всегда, когда цена не задана, что оставляет ее с начальным значением 0, цикл if, указанный выше, оценивается как истинный, а цена устанавливается равной -1. То есть, он считает 0 равным «e».
Как это можно объяснить?
Изменить: когда цена указана как 0 (после инициализации), поведение неустойчиво: иногда значение if оценивается как true, иногда оно оценивается как false.
вы делаете ==
который сортирует типы для вас.
0
– это int, поэтому в этом случае он будет отличать 'e'
от int. Который не обрабатывается как один, и станет 0
. Строка '0e'
станет 0
и будет соответствовать!
использовать ===
Это связано с тем, как PHP выполняет операцию сравнения, которую обозначает оператор сравнения ==
:
Если вы сравниваете число со строкой или сравниваете числовые строки, то каждая строка преобразуется в число, а сравнение выполняется численно. […] Преобразование типа не происходит, когда сравнение
===
или!==
поскольку это предполагает сравнение типа, а также значения.
Поскольку первым операндом является число ( 0
), а второе – строка ( 'e'
), строка также преобразуется в число (см. Также таблицу Сравнение с различными типами ). На странице руководства по типу строковых данных определено, как выполняется преобразование строки в число :
Когда строка оценивается в числовом контексте, результирующее значение и тип определяются следующим образом.
Если строка не содержит символов
.
','e
'или'E
', а числовое значение вписывается в ограничения типа integer (как определеноPHP_INT_MAX
), строка будет оцениваться как целое число. Во всех остальных случаях он будет оцениваться как плавающий.
В этом случае строка является 'e'
и поэтому она будет оцениваться как float:
Значение задается начальной частью строки. Если строка начинается с действительных числовых данных, это будет используемое значение. В противном случае значение будет равно
0
(ноль). Действительные числовые данные являются необязательным знаком, за которым следуют одна или несколько цифр (необязательно содержащие десятичную точку), за которыми следует необязательный показатель. Показателем является «e
» или «E
», за которым следует одна или несколько цифр.
Поскольку 'e'
не начинается с действительных числовых данных, он вычисляет float 0
.
Оператор == будет пытаться сопоставить значения, даже если они имеют разные типы. Например:
'0' == 0 will be true
Если вам требуется сравнение типов, используйте оператор ===:
'0' === 0 will be false
Ваша проблема – оператор с двойным равенством, который будет приписывать правильный член типу слева. Используйте строгую, если хотите.
if($item['price'] == 'e') { $item['price'] = -1; }
Вернемся к вашему коду (скопировано выше). В этом случае, в большинстве случаев, $ item ['price'] является целым числом (кроме случаев, когда оно равно e, очевидно). Таким образом, по законам PHP, PHP будет приписывать "e"
целым, что дает int(0)
. (Не верьте мне? <?php $i="e"; echo (int)$i; ?>
).
Чтобы легко уйти от этого, используйте оператор тройного равенства (точного сравнения), который будет проверять тип и не будет подразумевать тип.
PS: PHP забавный факт: a == b
не означает, что b == a
. Возьмите свой пример и отмените его: if ("e" == $item['price'])
никогда не будет выполняться при условии, что $ item ['price'] всегда является целым числом.
В PHP есть довольно удобный метод для проверки сочетания «0», «false», «off» как «false» и «1», «on», «true» как == true, который часто игнорируется. Это особенно полезно для разбора аргументов GET / POST:
filter_var( $item['price'], FILTER_VALIDATE_BOOLEAN );
Это не относится к этому случаю использования, но с учетом сходства и факта, что это результат поиска, который обычно обнаруживается при задании вопроса о проверке (string) «0» как false. Я думал, что это поможет другим.
Вы должны использовать ===
вместо ==
, потому что обычный оператор не сравнивает типы, которые будут вызывать типы элементов. Но ===
учитывает тип элементов.