Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

People also ask

Is 0 an integer PHP?

PHP converts the string to an int, which is 0 (as it doesn't contain any number representation).

Is equal to string PHP?

The most common way you will see of comparing two strings is simply by using the == operator if the two strings are equal to each other then it returns true. This code will return that the strings match, but what if the strings were not in the same case it will not match.

What does == and === mean in PHP?

== Operator: This operator is used to check the given values are equal or not. If yes, it returns true, otherwise it returns false. Syntax: operand1 == operand2. === Operator: This operator is used to check the given values and its data type are equal or not. If yes, then it returns true, otherwise it returns false.

Can you compare a string and a number in PHP?

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.


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.


This is due to how PHP does the comparison operation that the == comparison operator denotes:

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. […] The type conversion does not take place when the comparison is === or !== as this involves comparing the type as well as the value.

As the first operand is a number (0) and the second is a string ('e'), the string is also converted to a number (see also table Comparison with Various Types). The manual page on the string data type defined how the string to number conversion is done:

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.

In this case the string is 'e' and thus 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.

As 'e' does not start with a valid numeric data, it evaluates to float 0.


"ABC" == 0

evaluates true because first "ABC" is converted to integer and becomes 0 then it is compared to 0.

This is an odd behaviour of the PHP language: normally one would expect 0 to be promoted to string "0" and then compared to "ABC" with a result false. Perhaps that's what happen in other languages like JavaScript where the weak comparison "ABC" == 0 evaluates false.

Doing a strict comparison solves the problem:

"ABC" === 0

evaluates false.

But what if I do need to compare numbers as strings with numbers?

"123" === 123

evaluates false because the left and right term are of different type.

What is actually needed is a weak comparison without the pitfalls of PHP type juggling.

The solution is to explicit promote the terms to string and then do a comparison (strict or weak doesn't matter anymore).

(string)"123" === (string)123

is

true

while

(string)"123" === (string)0

is

false


Applied to the original code:

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

The == operator will try to match values even if they are of different types. For instance:

'0' == 0 will be true

If you need type comparison as well, use the === operator:

'0' === 0 will be false

Your problem is the double equal operator, which will typecast the right member to the type of the left. Use strict if you prefer.

if($item['price'] == 'e') {
    $item['price'] = -1;
}

Let's go back to your code (copied above). In this case, in most cases, $item['price'] is an integer (except when it is equal to e, obviously). As such, by laws of PHP, PHP will typecast "e" to integer, which yields int(0). (Don't believe me? <?php $i="e"; echo (int)$i; ?>).

To easily get away from this, use the triple equal (exact comparison) operator, which will check the type and will not implicitly typecast.

P.S: a PHP fun fact: a == b does not imply that b == a. Take your example and reverse it: if ("e" == $item['price']) will never actually be fulfilled provided that $item['price'] is always an integer.


There's a rather handy method in PHP for validating a mix of "0", "false", "off" as == false and "1", "on", "true" as == true which is often overlooked. It's particularly useful for parsing GET/POST arguments:

filter_var( $item['price'], FILTER_VALIDATE_BOOLEAN );

It's not wholy relevant to this use-case but given the similarity and fact this is the result search tends to find when asking the question of validating (string)"0" as false I thought it would help others.

http://www.php.net/manual/en/filter.filters.validate.php


You should use === instead of ==, because the ordinary operator does not compare the types. Instead it will attempt to typecast the items.

Meanwhile the === takes in consideration type of items.

  • === means "equals",
  • == means "eeeeh .. kinda looks like"