0

I'm wondering why this works the way it does:

var_dump(5 == "5 AND SOME TEXT");

output:

bool(true)

This same output is also achieved when comparing floats like this:

var_dump(1.234 == "1.234 AND SOME TEXT");

This must be an intentional effect since it's quite a basic thing and works in multiple PHP versions. I just don't see how this could be intended.

reveance
  • 126
  • 7
  • 3
    PHP is trying it's best to convert your string to a float because the first type in your comparison is a float, use a === if you also want to check type. https://www.php.net/manual/en/language.operators.comparison.php and https://www.php.net/manual/en/types.comparisons.php are a must read – Scuzzy Aug 04 '19 at 22:29
  • That's the way the language is done, probably because that was considered to be the most useful way of dealing with string to number cast at the time. Sadly, that makes this question off-topic for this site. – Blackhole Aug 04 '19 at 22:30
  • Yes I know about the identity check, I just wanted to why this works the way it does when not using identity. You answered that in your first comment and is also explained more extensively in the docs you linked. I guess basically it does a floatval or intval depending on which variable it's checked against and that strips away everything after the value, which makes the comparison true after that... – reveance Aug 04 '19 at 22:40

1 Answers1

6

When you're using the equality operator (==), PHP performs type juggling if the two values are not of the same type. When comparing a number to a string, it will try to cast that string to a number.

When casting a string to a number, if the string starts with a valid numeric value, that will be used. As soon as a non-numeric value is encountered, PHP will stop processing the rest of the string (if the string doesn't start with a number, PHP will turn it into 0). So your string "5 AND SOME TEXT" starts with a valid numeric value (5) but as soon as PHP finds that space it stops and you end up with the numeric value 5. Since 5 == 5, your result is true. The same is true for your other string, "1.234 AND SOME TEXT" is a valid number up to the first space.

There are two ways to work around this problem:

  • Use the identical operator (===). This will ensure that no type juggling is done so the result of 5 === "5 AND SOME TEXT" will be false. The downside is that since you're comparing a numeric type to a string, the result of 5 === "5" will also be false since the two values are of different types. This may not be what you want.
  • Cast your number to a string. Then, both values are strings and no type juggling takes place. You'll end up with "5" == "5 AND SOME TEXT" (or (string)5 == "5 AND SOME TEXT"), both of which will be false. But if the right side value is actually numerically correct, you'll get the result you want: "5" == "5" (or (string)5 == "5") will return true.
rickdenhaan
  • 10,857
  • 28
  • 37
  • Thank you, I actually did have a use for it and your second suggestion to work around the problem seems to be a great solution :) – reveance Aug 04 '19 at 22:42