Why does PHP consider 0 to be equal to a string?

Sérgio Domingues picture Sérgio Domingues · Jul 27, 2011 · Viewed 28.9k times · Source

I have the following piece of code:

$item['price'] = 0;
/* Code to get item information goes in here */
if($item['price'] == 'e') {
    $item['price'] = -1;
}

It is intended to initialize the item price to 0 and then get information about it. If the price is informed as 'e' it means an exchange instead of a sell, which is stored in a database as a negative number.

There is also the possibility to leave the price as 0, either because the item is a bonus or because the price will be set in a later moment.

But, whenever the price is not set, which leaves it with the initial value of 0, the if loop indicated above evaluates as true and the price is set to -1. That is, it considers 0 as equal to 'e'.

How can this be explained?

When the price is provided as 0 (after initialization), the behavior is erratic: sometimes the if evaluates as true, sometimes it evaluates as false.*

Answer

Nanne picture Nanne · Jul 27, 2011

You are doing == which sorts out the types for you.

0 is an int, so in this case it is going to cast 'e' to an int. Which is not parsable as one and will become 0. A string '0e' would become 0 and would match!

Use ===

From PHP.net:

Comparisons between strings and numbers using == and other non-strict comparison operators currently work by casting the string to a number, and subsequently performing a comparison on integers or floats. This results in many surprising comparison results, the most notable of which is that 0 == "foobar" returns true.

However this behavior was changed in PHP 8.0:

When comparing to a numeric string, PHP 8 uses a number comparison. Otherwise, it converts the number to a string and uses a string comparison.

PHP 7

0 == 'foobar' // true
0 == '' // true
4 == '4e' // true (4e is cast as a number and becomes 4)

PHP 8 converts numbers to strings before making comparisons

0 == 'foobar' // false
0 == '' // false
4 == '4e' // false ('4e' is considered non-numeric therefore 4 is cast as a string and becomes '4')

This is a major change therefore it was implemented in a new major PHP version. This change breaks backward compatibility in scripts that depend on the old behavior.