4
votes

I encountered a strange and unexpected behavior in PHP while comparing some string values. The first two statements below return true when I would expect them to return false. The last statement returns false as expected. I'm aware of PHP's Type Juggling, but what I understand from the docs is that type juggling happens when you are comparing two different data types like a string and an integer. In the examples below though both literals are strings. Does this mean that when you are doing string comparison in PHP it inspects both strings to see if they look like integers and if so type casts the both of them to integers and then compares those integer values. So my question is under what conditions does this behavior happen, how exactly does string comparison work in PHP?

var_dump("10" == "10.0000");
var_dump("10" == "+10.");
var_dump("10" == "10 ");

#output
bool(true)
bool(true)
bool(false)

Updates

So baba's answer below comparison involves numerical strings really helped in getting me to understand what's going on. The function is_numeric will return to you whether or not a string is considered to be a numeric string. interestingly "10 " is not considered a numeric string but " 10" is. I dug around the PHP source code and I believe the implementation of is_numeric is in the is_numeric_string_ex function. From that one can tell exactly when PHP will treat a string as a numeric string.

3
You could just use === or the more explicit strcmp/strcasecmp instead of accepting type juggling.DCoder
I know about those options. I'm not looking for alternatives I wish to understand the == operator and exactly when and why it applies type jugglingMarwan Alsabbagh
Don't use the == operator. Like many PHP features it contains too much magic. You can try to understand all exceptions of type juggling, but it's best to avoid it.GolezTrol

3 Answers

2
votes

You are getting error because of the position of the space this would return true

var_dump("10" == " 10"); // true

So if you RUN

var_dump("10" == "10 "); //false

What you are actually Running is because it would be treated as a string

var_dump("10" == 0); //false

This is because Type juggling would convert "10 " to 0 this is in the PHP Documentation

FROM PHP DOC

TRUE if $a is equal to $b after type juggling.

If you compare a number with a string or the comparison involves numerical strings, then each string is converted to a number and the comparison performed numerically. These rules also apply to the switch statement. The type conversion does not take place when the comparison is === or !== as this involves comparing the type as well as the value.

If you want to trick type juggling

var_dump("10" == 0 + "10 ");  // true

This is Because

An example of PHP's automatic type conversion is the addition operator '+'. If either operand is a float, then both operands are evaluated as floats, and the result will be a float. Otherwise, the operands will be interpreted as integers, and the result will also be an integer. Note that this does not change the types of the operands themselves; the only change is in how the operands are evaluated and what the type of the expression itself is.

1
votes

I suppose the definite answer lies buried somewhere in the vastness of compare_function in php-src/Zend/zend_operators.c and the macros used in there.

0
votes

In this case, all the 'strings' except the last one, are treated like floats or integers, and then compared. Thats why line 1 and 2 give a true.

In line 3 there is a space in the string, and that means for php that is is a 'real' string, and that line gets strings compared.

I do not like loose typed languages either, but for php this is the way it works.