У меня есть следующий код:
$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. Я думал, что это поможет другим.
Вы должны использовать === вместо == , потому что обычный оператор не сравнивает типы, которые будут вызывать типы элементов. Но === учитывает тип элементов.