PHP empty var == 0? - php

In php 5
$my_var = "";
if ($my_var == 0) {
echo "my_var equals 0";
}
Why it evaluates true? Is there some reference in php.net about it?

PHP is a weakly typed language. Empty strings and boolean false will evaluate to 0 when tested with the equal operator ==. On the other hand, you can force it to check the type by using the identical operator === as such:
$my_var = "";
if ($my_var === 0) {
echo "my_var equals 0";
} else {
echo "my_var does not equal 0";
}
This should give you a ton of information on the subject: How do the PHP equality (== double equals) and identity (=== triple equals) comparison operators differ?

A string and an integer are not directly comparable with ==. So PHP performs type juggling to see if there is another sensible comparison available.
When a string is compared with an integer, the string first gets converted to an integer. You can find the details of the conversion here. Basically, since "" is not a valid number, the result of the conversion is 0. Thus, the comparison becomes 0 == 0 which is clearly true.
You'll probably want to use the identity comparison === for most (if not all) your comparisons.

This is due to the type coercion that comes from the equality operator you are using.
The PHP manual has the Type Comparison tables to shed a light on this.
Its generally considered a good practice to utilize the identical operator === instead, as to avoid such corner(?) cases.

In your first line, you define $my_var as string.
Inside the comparison you compare that variable with a constant integer.
If you want exact comparison (I don't know why you need to compare a string with an integer without any cast), you should use the ===:
if ($my_var === 0) {
echo "my_var equals 0";
}
That will never echo the message.
The PHP manual defines in Comparison Operators section, the operator == as:
TRUE if $a is equal to $b after type juggling.
So, the important thing here is type juggling.
As a matter of fact, in PHP Manual: types comparisons, the second table tell you exactly that integer 0 equals string "".

here is the reference in the php manual about boolean values
http://www.php.net/manual/en/language.types.boolean.php
and here is the reference for the NULL value
http://www.php.net/manual/en/language.types.null.php
$my_var = '';
if ($my_var == 0) {
echo "my_var equals 0"
}
evaluates to true because "" is the same as NULL which evaluates to false or 0

Related

PHP compare equality, empty string, "0" and 0

I learned that the empty string "", 0 and "0" all mean false in php. I wonder does php take that into account when it comes to comparing equality.
$str = "";
echo ($str == "0") ? "yes" : "no"; // prints "no" (A)
echo ($str == 0) ? "yes" : "no"; // prints "yes" (B)
Line A suggests that php is comparing $str and "0" as if they are all strings, ignoring that they both can mean false. But line B is comparing their "false" interpretation.
So is it the case that php firstly checks if the two values have the same type, if so it checks equality assuming the same type; if not, it uses the boolean meanings of the values (is there type casting involved?)
I learned that the empty string "", 0 and "0" all mean false in php.
This statement is false. Empty string, 0 and "0" are false when casted to boolean type. Otherwise they are either empty string, integer zero or string with one character, respectively.
== checks values of two variables. If their types are different, some casting happens and unpredictable (for rookies) results come up.
=== checks values of two variables and their types.
Anyway, when you compare "0" == "", PHP interpreter compares two strings which are different. But when you go with 0 == "" it first changes numeric string to integer. Empty string equals 0. So we end up with 0 == 0 which is true.
Note: "8abc" becomes 8 after casting to integer. abc8 becomes 0 when casted
Manual on:
- Types casting (juggling)
- Types comparison
There are two equality comparator in PHP
When the types are the same, they behave in the same way.
When the types are different, it all depends: PHP does not cast both values to booleans. It depends on the types of both operands, and there is a table to know what PHP will do (see second link).
I recommend reading this stackoverflow question
How do the PHP equality (== double equals) and identity (=== triple equals) comparison operators differ?
Also, the PHP manual for comparison
http://au.php.net/manual/en/language.operators.comparison.php
// double equal will cast the values as needed followin quite complex rules
0 == '0' // true, because PHP casted both sides to numbers
// triple equals returns true only when type and value match
0 === '0' // false
$str = "";
//Comparing two strings, no implicit type conversion happens. Since
// "" is not equal "0", result is FALSE
echo ($str == "0") ? "yes" : "no"; // prints "no" (A)
//Comparing a STRING to an INT,implicit conversion happens to convert
// the string "" to an INT. Since "" has no digits, it's evaluated
// to 0. Hence, result of comparison is TRUE
echo ($str == 0) ? "yes" : "no"; // prints "yes" (B)
Use "===" for more accurate comparison.

PHP test if ('a' == 0) [duplicate]

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.*
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"
Basically, always use the === operator, to guarantee type safety.
I think it is best to show by examples I did, while running into the same weird behavior. See my test case and hopefully it will help you understand the behavior better:
// Normal comparison using the == Operator
echo (0 == "0"); // true
echo (0 == "a"); // true
echo (0 == "safta!"); // true
echo (1000 == "bla"); // false. It appears that PHP has a weird behavior only with the number / string 0 / "0" according to the past 3 examples.
echo (23 == "23"); // true. So as we said, PHP has a problem (not a problem but weird behavior) only when the number / string 0 (or "0") is present
echo (23 == "24"); // false. values aren't equal (unlike last example). The type is less relevant with the == operator as we can see.
// Now using the === and !== Operators
echo ("0" === 0); // false, since === requires both value and type to be the same. Here, type is different (int vs string)
echo ("0" !== 0); // true because they aren't the same in terms of === comparison (type is different and that's why it's true)
echo ("bla" === "blaa"); // false because the values are not the same. The type is the same, but === checks for both equal type and equal value.
//Now using casting and === Operator:
echo ((string)123 === "123"); // true. The casting of the int 123 to string changed it to "123" and now both variables have same value and are of same type
echo ((int)"123" === 123); // true. The casting of the string 123 to int, changed it to int, and now both variables are of same value and type (which is exactly what the === operator is looking for)
// Now using casting and == Operator. Basically, as we've seen above, the == care less for the
// type of var, but more to the value. So the casting is less relevant here, because even
// without casting, like we saw earlier, we can still compare string to int with the == operator
// and if their value is same, we'll get true. Either way, we will show that:
echo ((string)123 == "123"); // true. The casting of the int 123 to string changed it to "123" and now both vars have same value and are of same type
echo ((int)"123" == 123); // true. The casting of the string 123 to int, changed it to int, and now both vars are of same value and type (which is exactly what the === operator is looking for)

Why does 1234 == '1234 test' evaluate to true? [duplicate]

This question already exists:
Closed 10 years ago.
Possible Duplicate:
php == vs === operator
An easy answer for someone I'm sure. Can someone explain why this expression evaluates to true?
(1234 == '1234 test')
Because you are using the == (similarity) operator and PHP is coercing the string to an int.
To resolve it use the === (equality) operator, which checks not only if the value is the same, but also if the data type is the same, so "123" string and 123 int won't be considered equal.
In PHP (and JavaScript -- which has slightly different behavior), the comparison operator == works differently than it does in strongly-typed languages like C or Java. The === operator has the behavior that you most likely expect. Below is a breakdown of the two comparison operators as they apply to PHP.
==
This operator is officially known as the "equality" operator, though that doesn't really fit the normal definition of the word "equality". It does what is known as a type-juggling comparison. If the types of both operands don't match (in your example, 1234 was an integer and 1234 test was a string), PHP will implicitly cast the operands to each others' types and test the equality of the newly-typed values as shown below:
<?php
var_dump( (int) 'hi' ); // int(0)
var_dump( (string) 0 ); //string("0")
var_dump( 'hi' == 0 ); // bool(true)
var_dump( (int) '1hi' ); // int(1)
var_dump( 1 == '1hi' ); // bool(true)
It has a counterpart (type-juggling) inequality operator, !=.
===
The === operator, known as the "identical" operator, performs a strict check of the value and type of both operands and does not perform any implicit casts. Therefore, "0" does not === 0 and "1234 test"does not === 1234.
<?php
var_dump( '1234 test' === 1234 ); // bool(false)
It has a counterpart (strict) inequality operator, !==.
Quirks
Note that the === operator has behavior on objects that is considered strange by some. Say we have class A and variables $a and $b as defined below:
<?php
class A {
public $property = 'default value';
}
$a = new A();
$b = new A();
You might expect var_dump($a === $b); to output bool(true). It will actually return false. When used upon objects, the operator actually checks if both operands are references to the same object. The == operator, in this instance, works by checking the properties of the objects, so $a == $b.
PHP Manual Links
Comparison operators
Type juggling
When casting a string to an integer, any numeric characters up to the first non-numeric character becomes the number. Thus '1234 test' becomes 1234 because space is not a numeric character.
Thus 1234 == '1234 test'
If you want to force a string comparison, you should cast to string:
''.(1234) == '1234 test' // implicit
(string) 1234 == '1234 test' // explicit
strval(1234) == '1234 test' // procedural
You are loosely comparing two different types of data (an integer and a string). PHP has a very detailed chart of how comparisons work in their system when using the loose comparison binary operator (==):
http://php.net/manual/en/types.comparisons.php
If you want to ensure that the types are also in sync, that is that they are both integers or both strings, use the strong type comparison operator (===).
Note that, when using this operator, this will also return false:
1234 === '1234'
If you are unsure of your types when comparing, you can couple the strong-type comparison with PHP typecasting:
$a = 1234;
$b = '1234';
if ($a === $b) { } // Will not fire, as it is false
if ((int)$a === (int)$b) { } // Will fire, as it is true
The double equals will tell php to parse an int from the string. The string will evaluate to the integer 1234. Use triple equals '===' to get exact comparison.
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
var_dump(0 == "a"); // 0 == 0 -> true

Comparison Operator - Type Juggling and Booleans

I've been reading the PHP Docs on Type Juggling and Booleans but I still don't understand why this comparison evaluates as true. My [incorrect] understanding tells me that in the below if statement, the integer 0 is considered FALSE and "a", being a non-empty string is considered TRUE. Therefore, I expected this comparison to resolve to FALSE == TRUE and ultimately, FALSE. Which part did I get wrong?
<?php
if(0 == "a"){
$result = "TRUE";
}else{
$result = "FALSE";
}
//$result == "TRUE"
?>
http://codepad.viper-7.com/EjxBF5
When PHP does a string <=> integer comparison, it attempts to convert the string to a number in an intelligent way. The assumption is that if you have a string "42" then you want to compare the value 42 to the other integer. When the string doesn't start with numbers, then its value is zero.
From the docs:
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).
This behavior is also inferred in the comparison docs (look at the first line in the first example).
Your mistake is that you assume operator == coerces each of its operands to boolean before comparing them. It does no such thing.
What happens is that since you are comparing an integer to a string, the string is converted to an integer (in this case "a" converts to 0) and then the comparison 0 == 0 is performed.
It will work if you use a strict comparison === instead of ==. The strict comparison also checks the type of the variables, so 0 === 'a' would be false.

What does "===" mean? [duplicate]

This question already has answers here:
How do the PHP equality (== double equals) and identity (=== triple equals) comparison operators differ?
(13 answers)
Closed 4 months ago.
I've noticed someone using the PHP operator === which I can't make sense out of. I've tried it with a function, and it corresponds in crazy ways.
What is the definition of this operator? I can't even find it in the declaration of PHP operators.
$a === $b (Identical)
TRUE if $a is equal to $b, and they are of the same type. (introduced in PHP 4)
PHP Docs
http://www.php.net/ternary
$a == $b Equal TRUE if $a is equal to $b, except for (True == -1) which is still True.
$a === $b Identical TRUE if $a is equal to $b, and they are of the same type.
> "5" == 5;
True
> "5" === 5;
False
You can read here, short summary:
$a == $b Equal TRUE if $a is equal to $b after type juggling.
$a === $b Identical TRUE if $a is equal to $b, and they are of the same type.
In PHP you may compare two values using the == operator or === operator. The difference is this:
PHP is a dynamic, interpreted language that is not strict on data types. It means that the language itself will try to convert data types, whenever needed.
echo 4 + "2"; // output is 6
The output is integer value 6, because + is the numerical addition operator in PHP, so if you provide operands with other data types to it, PHP will first convert them to their appropriate type ("2" will be converted to 2) and then perform the operation.
If you use == as the comparison operator with two operands that might be in different data types, PHP will convert the second operand type, to the first's. So:
4 == "4" // true
PHP converts "4" to 4, and then compares the values. In this case, the result will be true.
If you use === as the comparison operator, PHP will not try to convert any data types. So if the operands' types are different, then they are NOT identical.
4 === "4" // false
$x == $y is TRUE if the value of the $x and $y are same:
$x = 1; //int type
$y = "1"; //string type
if ($x == $y) {
// This will execute
}
$x === $y TRUE if the value of the $x and $y are same and type of $x and $y are same:
$x = 1; //int type
$y = "1"; //string type
if ($x === $y) {
// This will not execute
}
You'll see this operator in many dynamically typed languages, not just PHP.
== will try to convert whatever it's dealing with into types that it can compare.
=== will strictly compare the type and value.
In any dynamically typed language you have to be careful with ==, you can get some interesting bugs.
The ternary === is less convenient, but it's safer. For comparisons you should always give some additional thought to whether it should be === or ==
The triple equals sign === checks to see
whether two variables are equal and of the same type.
For PHP, there many different meanings a zero can take
it can be a Boolean false
it could be a null value
It could really be a zero
So === is added to ensure the type and the value are the same.
See Double and Triple equals operator in PHP that I got for googling on "PHP three equals operator".
At one point it says that:
A double = sign is a comparison and tests whether the variable / expression / constant to the left has the same value as the variable / expression / constant to the right.
A triple = sign is a comparison to see whether two variables / expresions / constants are equal AND have the same type - i.e. both are strings or both are integers.
It also gives an example to explain it.
"===" matching the value in the variable as well as data type of the variable.

Categories