Understanding PHP – A Journey into the darkness…

Posted in PHP by Dan on July 31st, 2009

I knew PHP was a bit crufty before I got seriously involved with it. I’ve been trying to avoid writing a rant about how horrible it is as the web has enough of those already and, after all, it doesn’t really matter, does it? Still, to maintain my sanity I’ve been maintaining a list of everything that’s bad about PHP, mostly for my own amusement. However, the most recent entry on my list cannot be allowed to pass without comment.

"01a4" != "001a4"

We start with something simple and non-controversial. If you have two strings that contain a different number of characters, they can’t be considered equal. The leading zeros are important because these are strings not numbers.

"01e4" == "001e4"

However, PHP doesn’t like strings. It’s looking for any excuse it can find to treat your values as numbers. And here we have it. Change the hexadecimal characters in those strings slightly and suddenly PHP decides that these aren’t strings any more, they are numbers in scientific notation (PHP doesn’t care that you used quotes) and they are equivalent because leading zeros are ignored for numbers. To reinforce this point you will find that PHP also evaluates "01e4" == "10000" as true because these are numbers with equivalent values.  This is documented behaviour, it’s just not very sensible.

Enter ===

At this point the PHP apologists chime in with the suggestion to use the === operator. This is an equality operator that compares not only the values of the arguments but their types as well.  Both sides must have the same type as well as identical values. This doesn’t seem like it should make any difference as the literals on both side of the comparison already have identical types, regardless of whether that type is string or integer. Of course that’s not the case and when you use the extra equals sign the values remain as strings rather than being interpreted as integers. "01e4" === "001e4" evaluates to false (correct, but not entirely convincing).

"0x001a4" == 0x01a4

So it seems that the rule in PHP is that if the contents of a string can be parsed as a numeric literal then, for comparisons, they are, as we see with the above hexadecimals (note the difference in notation from the first example, specifically the use of the 0x prefix). Leading zeros are ignored when numbers are involved.

"0012" != 0012

Unfortunately that’s not the full story as the final example shows. Like many other languages, PHP interprets numbers beginning with a zero as octal values, but not when that number is within a string. This is completely inconsistent with the way it processes hexadecimal values and scientific notation within strings.