Тип литья и сравнение с Loose Operator "=="

У меня есть проблема, которая сбивает меня с толку. Я заметил это раньше, но до сих пор не обращал на это внимания. Я пытался написать собственный чек для целых строк. Я знаю is_numeric() но этого недостаточно, поскольку он считает float как числовое значение не только integers а is_int() которое не работает с строковыми числами.

Я сделал что-то подобное этому

 $var1 = 'string'; $var2 = '123'; var_dump( (int)$var1 == $var1);// boolean true var_dump((int)$var2 == $var2);// boolean true var_dump((int)$var1);//int 0 var_dump($var1);//string 'string' (length=6) 

Как и ожидалось, второй дамп var выводит true, так как я ожидаю, что при свободном сравнении php число строк и целочисленных версий будет равным.

Однако, во-первых, я не понимаю, почему это так. Я попробовал кастинг для bool и это все равно дает мне тот же результат.

Я попытался присвоить cast var новому переменному и сравнить два, все тот же результат

Это что-то я делаю неправильно или это ошибка php?

*** Примечание. Я не сравниваю типы здесь. Я на самом деле пытаюсь воспользоваться тем фактом, что int 0 не равно string 'string' .

Я написал свою целую проверку по-другому, поэтому мне не нужны альтернативы для этого.

*** Edit. Я сделал некоторую дополнительную проверку, и получается, что 0 == 'string' истинно. Как это возможно?

*** Изменить 2 На вопрос несколько правильных ответов. Спасибо всем, кто ответил.

Это не ошибка, это особенность . Любая строка может быть записана в целое число, но приведение будет возвращать 0, если строка не начинается с целочисленного значения. Кроме того, при сравнении целого числа и строки строка выводится в целое число, а затем выполняется проверка с двумя целыми числами . Из-за этого правила примерно любая случайная строка «равна» нулю. (Чтобы обойти это поведение, вы должны использовать strcmp , поскольку он выполняет явное сопоставление строк путем литья чего-либо, переданного в строку.)

Чтобы убедиться, что я имею дело с целым числом, сначала я должен использовать is_numeric , а затем преобразовать строку в int и убедиться, что stringified int соответствует входному значению.

 if (is_numeric($value) && strcmp((int)$value, $value) == 0) { // $value is an integer value represented as a string } 

Согласно php.net http://php.net/manual/en/language.operators.comparison.php :

 var_dump(0 == "a"); // 0 == 0 -> true 

Итак, я думаю, что это жонглирование типами, и фактически литье обеих сторон в int. Затем сравните либо сумму значений ascii, либо значений ascii каждого соответствующего индекса в строке.

Прежде всего в математиках '=' называется транзитивным b / c (A = B и B = C => A = C).

Это не относится к PHP «==»!

 (int)$var1 == $var1 

В этом случае PHP будет отличать 'string' до 0 – это соглашение.

Тогда == – оператор будет неявно иметь вторую операнду 'string', также быть отлитой в integer ->, а также 0.

Это приводит к истине.

Вы сделали ошибку со своим сообщением, правильный результат:

 bool(true) bool(true) int(0) string(6) "string" 

Что происходит, так это:

  1. Поскольку вы передаете переменную целому числу и сравниваете ее с целым числом со свободным сравнением == , PHP сначала будет вводить строку в целочисленное целое, а более явную, но 100% эквивалентную форму: if((int)$var1 == (int) $var1)
  2. См. 1), то же самое относится и здесь
  3. Он печатает int(0) , как и следовало ожидать, потому что он не может проанализировать число, оно вместо этого вернет 0 .
  4. Печать string(6) "string" – как и ожидалось

Если вы хотите также сравнить типы переменных, вы должны использовать === .

Примечание. Этот ответ отвечает на соответствующий вопрос о движке шаблонов Twig , который был помечен как дубликат, и перенаправляет сюда.

Поскольку контекст отличается, этот ответ предоставляется тем членам сообщества SO, которые могут извлечь выгоду из дополнительных сведений, специально связанных с веточкой исключительно.

TL; DR : см. Этот пост. Чем отличаются отношения равенства PHP (== double equals) и идентичности (=== triple equals)?

проблема

контекст

  • Twig template engine (последняя версия от Пт 2017-01-27T05: 12: 25)

сценарий

  • DeveloperYlohEnrohK использует оператор сравнения в выражении twig
  • РазработчикYlohEnrohK замечает неожиданные результаты при использовании оператора сравнения равенства

Вопросов

  • Почему оператор сравнения равенства ( == ) дает неожиданные результаты в Twig?
  • Почему следующие результаты дают разные результаты?

     {{dump (0 == 'somekey')}} ==> true
     {{dump (0 | lower == 'somekey')}} ==> false
    

Решение

  • Поскольку Twig основан на PHP, кастинг , неявное преобразование типов и семантика сравнения PHP применяются также к шаблонам Twig.
  • Если DeveloperYlohEnrohK намеренно и конкретно не использует поведение неявного преобразования типов в PHP, выражение сравнения почти наверняка даст противоречивые и неожиданные результаты.
  • Это хорошо известное обстоятельство , подробно описанное в этой публикации SO на равенстве PHP .
  • Решение. Как и в случае со стандартным PHP, если не учитывается известное обстоятельство , использование === в Twig гораздо реже приводит к неожиданным результатам.

Ловушки

  • На момент написания этой статьи механизм шаблонов Twig не поддерживал === же, как стандартный PHP
  • У Twig есть замена === используя то same as
  • Из-за этого обработка этого известного обстоятельства немного отличается между PHP и Twig.

Смотрите также

Вот функция, которая более строго проверяет либо строку int, либо целочисленную строку.

 function isIntegerNumeric($val) { return ( is_int($val) || ( !is_float($val) && is_numeric($val) && strpos($val, ".") === false ) ); } 

Это относительно быстро и позволяет избежать проверки строки, если это не так.