The issue of PHP strings equaling zero has come up a few times recently. Here’s a specific example:
[sourcecode lang=”php”]
if ( ‘php’ == 0 ) {
echo "Equals zero!n";
} else {
echo "Not equal to zeron";
}
[/sourcecode]
Running that will display Equals zero!
, which at first glance probably doesn’t make much sense. So what is going on here?
The first thing to look at is that the conditional involves two different variable types. The first is 'php'
, which is a string, and 0
which is an integer. Because we are using the ==
comparison operator instead of ===
there will be some type juggling. If we had used ===
instead the comparison will evaluate to false since there would be no type conversion.
For this comparison PHP will be using the integer context. That means our string 'php'
is going to be converted into an integer first, then the comparison will happen. You can picture this first step via:
[sourcecode lang=”php”]
var_dump( (int) ‘php’ );
[/sourcecode]
Which will show int(0)
. That isn’t a surprise given what we saw in the original code example. Just to make things more interesting, PHP strings when cast as an integer only sometimes become zero.
Now is a good time to point to the PHP documentation on the subject, specifically the “String conversion to numbers” section of the Strings page on php.net. That is where the rules of string conversion are outlined:
When a string is evaluated in a numeric context, the resulting value and type are determined as follows.
If the string does not contain any of the characters ‘.’, ‘e’, or ‘E’ and the numeric value fits into integer type limits (as defined by PHP_INT_MAX), the string will be evaluated as an integer. In all other cases it will be evaluated as a float.
The value is given by the initial portion of the string. If the string starts with valid numeric data, this will be the value used. Otherwise, the value will be 0 (zero). Valid numeric data is an optional sign, followed by one or more digits (optionally containing a decimal point), followed by an optional exponent. The exponent is an ‘e’ or ‘E’ followed by one or more digits.
A small modification to the orignal example demonstrates these rules in action:
[sourcecode lang=”php”]
if ( ‘7php’ == 0 ) {
echo "Equals zero!n";
} else {
echo "Not equal to zeron";
}
[/sourcecode]
This outputs Not equal to zero
, because '7php'
when converted to an integer gets a value of 7 instead of 0.
Even after understanding the steps that are involved there is still one piece that bothers me. The choice to use an integer context for things like 'php' == 0
. At first glace my expectation would be to have it evaluated in a string context, essentially something like 'php' == '0'
. It isn’t clear to me why PHP opted to use the integer context instead.
One final word on the scope of this issue. While I still think it is odd that the string gets cast as an integer instead of the other way around, I don’t think this is a big deal. I can’t recall a single time where I’ve ever run into this issue in a PHP app. I’ve only seen it come up in contrived examples like the ones above.
14 replies on “Why PHP Strings Equal Zero”
[…] Why PHP Strings Equal Zero → 8 seconds ago […]
Nice to read a blog post about this! Just this week I’ve found out this weird behaviour the hard way.
For some custom application I had to convert an array into an XML document. To add support for multiple tags with the same name in the same parent tag, I had to revert to using an array syntax with the subelements being expressed as an array with numeric keys like this: $xml = array(‘parent’ => array(0 => array(‘child’ => ‘value’), 1 => array(‘child’ => ‘othervalue’)));
However, when I needed to do some post-processing involving possible replacement of the keys/values, this got mixed up. In my case, the *integer* key, was replaced by a *string* key (0 vs ‘0’), which failed my checks (the same weird array syntax was also used to determine the necessity of renaming the keys).
It was solved by explicitly casting the integer key to a string, as you pointed to in the article.
A good general policy is to be explicit as possible. I like the flexibility of loosely typed vars in PHP, but you do have to know when it can come back to bite you.
Yeah, I agree. This actually was an unintended (and – to be honest – unexpected) side-effect of solving another bug pointed out by my customer, which made that key renaming necessary. And that is what bit me.
However, I might indeed want to come up with a better and more explicit syntax for the intended behaviour.
I don’t see an issue with string casting here but bad programming skills/habits. It is known that casting is in the work when comparing different types and it’s only natural that they are casted to the lowest common type, which is often the numeric type.
The developer who wrote `’php’ == 0` should be punished by copying 10 times the documentation excerpt you mentioned.
BTW the title of your article is not correct because as you mentioned “7php” is equivalent to 7, not zero.
I noted at the end of the post that I don’t think this is really a big deal. I haven’t seen in happen in non-example code, I suspect the number of times people hit this is relatively small. But if they do hit it I bet it is frustrating.
That is why I specifically choose not to say ‘all PHP strings’ in the post title.
This is a great post, thank you!
This issue or bug was truly getting me an headache! In my case was this condition that was making my application go wrong:
if($value == “NOW()”){
and I had to change it to:
if($value === “NOW()”){
because on the first case, if $value is 0 the condition would return TRUE (I was wondering why 0 would be same as “NOW()” string) instead of the expected false.
Many thanks!
well done for mentioning this. People who don’t get it, may get stumbled by it at some point.
… the solution is as you said: be a strict as possible…just not with absolutely everything…
cheers mr scott.
Great explanation of a confusing issue.
Ran into an actual bug because of this behaviour in some legacy code handling ldap today. When using ldap_get_entries the first element in the result array is ‘count’. This array was looped through and checked that ($key != ‘count) – this led to the first actual element always missing from the output…
It bit me w/ an array looping evaluation too. So should we always use === for evaluation?
$string =’bce0′;
How to determine if this string contains an integer. Can u help me to write a small program without using any built-in function like is_numeric,is_int etc?
At some point you need to use some PHP functions to check it. You could avoid the traditional integer checking ones and use
preg_match
like: