foreach, unexpected result for element, which key is 0 - php

I have this code
$arr = array(
"0"=>"http://site.com/somepage/param1/param2/0",
"1"=>"http://site.com/somepage/param1/param2/1",
"thispage" => "http://site.com/somepage/param1/param2/2",
"3"=> "http://site.com/somepage/param1/param2/3"
);
foreach ($arr as $k=>$v) {
if ($k == "thispage") {
echo $k." ";
}
else {
echo ''.$k.' ';
}
}
Its surprise, for first element "0"=>"http://site.com/somepage/param1/param2/0", not created link, (for other elements works fine)
If replace first element key 0 on something other, for example 4, now links created. What is wrong ?

This is happening because 0 == "thispage" and the first key is 0. To find out more about this, take a look at the PHP manual page about Type Juggling.
Use === ("is identical to") instead of == ("is equal to"), because 0 is equal to "thispage", but not identical.
This is what happens with ==:
$key takes the integer value of 0
PHP tries to compare 0 == "thispage"
in order to make the comparison, it needs to cast "thispage" to integer
the resulting comparison is 0 == 0, which is true
If you use ===:
$key takes the integer value of 0
PHP tries to compare 0 === "thispage"
since 0 is of a different type (integer) than "thispage" (string), the result is false

This is What you are doing wrong.
if ($k === "thispage") {
echo .$k." ";
}

Do the:
if ($k === "thispage")
You have to use identical comparison operator === as equal comparison operator won't help here, because
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.
thispage converted to number will return 0, so your if statement will match if you use equal comparison operator ==. When you do identical comparison === if type does not match it returns false.
You can read about comparison operators here.

Try this:
if ($k === "thispage") {
echo $k." ";
}

http://us.php.net/manual/en/language.types.array.php:
A key may be either an integer or a string. If a key is the standard representation of an integer, it will be interpreted as such (i.e. "8" will be interpreted as 8, while "08" will be interpreted as "08").
So in your case Stings "1", "2" and "3" are treated as integers.
To fix this use the === operator that check for type along with value.

The reason for the result you see is the comparison operator you use. == is too imprecise sometimes and can result in wierd things like this. Using the === will compare the values for exactness and will prevent the issue you have.
so:
foreach ($arr as $k=>$v) {
// this is the important thing
if ($k === "thispage") {
echo $k." ";
}
else {
echo ''.$k.' ';
}
}

Related

PHP: Strange behaviour with variable assignment

I'm declaring a var $t and assigning it a value of 0. I then reassign $t a new value of test. It then appears that $t is both 0 AND test. Here's the code:
$t = 0;
$t = "test";
if($t == 0 && $t == "test"){
echo "unexpected";
}else{
echo "expected";
}
The output is:
"unexpected"
Can someone please explain what is going on here? Is $t really two different values (0 and test) at the same time or am I missing something?
This "strange" behaviour results in because of PHP's type juggling. Since you're using loose comparison == to compare to an integer 0 the string test is being converted to an integer, which results in conversion to 0. See the Loose comparison == table. There in the row with the string php you'll see that it equals to the integer 0, which applies to all strings.
You should be using strict (type) comparison operators, i.e. ===.
You're not appending or concatenating so it shouldn't be. Try the identical comparison operator instead.
if($t === 0 && $t === "test"){
....
}
PHP MANUAL STATES:
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.
http://il.php.net/manual/en/language.types.string.php#language.types.string.conversion
So $t == 0 is true. You have to use strict comparison ===
Hey buddy use "===" operator for your comparison.
In php we can assign any value to a simple variable, it holds numeric, float, character, string, etc.
So always use "===" operator for unique or same value matching.

Strange logic behaviour in PHP - is this normal?

Can anyone figure out why this might happen in PHP (am using v5.4):
$value = 0;
$existing_value = "Unknown";
if ($value == $existing_value) {
echo "$value == $existing_value";
} else {
echo "$value != $existing_value";
}
This outputs as 0 == Unknown
Interestingly, $value = "0" (i.e. set as a string), evaluates to be false
Is this a known behaviour? Have I missed something in the documentation on this? Debugging this was driving me crazy earlier today!
Thanks for your help in advance...
This is caused by the automatic type casting, PHP uses.
When comparing an int value with a string using just ==, the string will be casted to an int, which in your case results in a 0 and hence a true evaluation.
See the respective PHP documentation for more information.
To circumvent this, you could use === instead of ==. The former includes a type check, which will make your condition evaluate to false:
$value = 0;
$existing_value = "Unknown";
if ($value === $existing_value) {
echo "$value === $existing_value";
} else {
echo "$value !== $existing_value";
}
When you compare a number with a string in PHP, as you do here, the string is converted to a number. Since the string "Unknown" is not numeric, it's converted to the number 0.
If you check for equality with the === operator, it won't perform type conversion and it'll evaluate as false.
http://php.net/manual/en/language.operators.comparison.php
You should have a look at the comparison tables in PHP Especially the loose comparison (using ==) section as compared to the strict comparison (using ===) section.

php variables comparison == vs ===

this is code:
$s = 0;
$d = "dd";
if ($s == $d) {
var_dump($s);
die(var_dump($d));
}
result is:
int 0
string 'dd' (length=2)
Please explain why.
why ($s == $d) results as true?
Of course, if === is used it will results as false but why this situation requires ===?
Shouldn't it be returned false in both situations?
Because (int)$d equals with 0 and 0=0
you must use strict comparison === for different character tyes (string) with (int)
Your $d is automatically converted to (int) to have something to compare.
When you compare a number to a string, the string is first type juggled into a number. In this case, dd ends up being juggled into 0 which means that it equates to true (0==0).
When you change the code to:
<?php
$s = 1;
$d = "dd";
if ($s == $d)
{
var_dump($s);
die(var_dump($d));
}
?>
You will find that it doesn't pass the if statement at all.
You can more details by reading up on comparison operators and type juggling.
The string "dd" is converted to int, and thus 0.
Another example :
if ( "3kids" == 3 )
{
return true;
}
And yes, this returns true because "3kids" is converted to 3.
=== does NOT auto convert the items to the same type.
Also : 0 == false is correct, but 0 === false is not.
See : http://php.net/manual/en/language.types.type-juggling.php
The string will try to parsed into a number, returns 0 if it is not in right number format.
As seen in the php website :
http://php.net/manual/en/language.operators.comparison.php
var_dump(0 == "a"); // 0 == 0 -> true
In PHP, == should be pronounce "Probably Equals".
When comparing with ==, PHP will juggle the file-types to try and find a match.
A string with no numbers in it, is evaluated to 0 when evaluated as an int.
Therefore they're equals.

Weird $key => $value comparison with PHP

I'm facing a weird issue with PHP. This simple example:
<?php
$array = array(
'zero',
'one',
'id' => 'two'
);
foreach ($array as $key => $value) {
if ($key == "id") {
echo "Key: ". $key .", value: ". $value ."\n";
}
}
?>
should (imho) output this:
Key: id, value: two
But it outputs
Key: 0, value: zero
Key: id, value: two
How is this possible: 0 == "id"?
When $key is 0 and gets compared to the string "id", the string ("id") will be converted to an integer. Since "id" can't be turned into a valid integer that conversion will yield 0, and the if statement becomes true.
Since you don't want the implicit conversion to happen between two types who aren't compatible use the more strict === version of ==. === will see if the variables are of the same type and has the same exact value.
if ($key === "id") {
...
}
Documentation PHP: Comparison Operators
Examples
var_dump (0 == (int)"id");
var_dump ((string)0 == "id");
var_dump (0 === "id");
var_dump (1.0 === 1);
output
bool(true)
bool(false)
bool(false)
bool(false) # be careful!
You are being bitten by a process called type juggling.
Try the following:
var_dump(0 == "id");
It will output bool(true).
PHP is performing integer comparison, and when it attempts to convert the string "id" to an integer, the result is 0. PHP will happily parse leading digits of a string and stop at the first non-numeric value, yielding integer 123 for strings like "123xyz". Because there are no leading digits in the string "id", it is parsed as integer 0.
The solution is to use ===, which compares the value and type of two variables, without attempting to juggle the types of the operands.
This:
$key == 'id'
...will make PHP do integer comparison, since the lvalue is an integer.
If you're wondering why this:
if ($key) { ... }
...wouldn't give the same result, well it's because the lvalue here (while omitted) is boolean, equivalent to:
if (true == $key) { ... }
Therefore, PHP will attempt boolean comparison. You can use the === operator to force a type check.
You can refer to the Type Comparison Tables and the Comparison Operators Table.
If you set the logic expression to take into account vartype
if (key === "id")
if will work. Just like #refp says.

Foreach loop issues in php

Here is some code I have: (p just echos plus adds a newline)
foreach ($vanSteps as $k => $reqInfo)
{
p($k);
if ('van' == $k) { p('The key is the van, continue'); continue; }//continue if we reached the part of the array where van is key
//do stuff
}
and I'm getting this output:
0
The key is the van, continue
1
2
3
van
The key is the van, continue
Why does the if statement return true when the key is 0? This foreach loop handles logic that applies when the key == 0 (and any other key except if the key is 'van') and this messes up the logic because it's return true when key is 0.
Any help?
Thank you.
Use === for this comparison. When PHP compares string and integer it first casts string to integer value and then does comparison.
See Comparison Operators in manual.
In PHP 'van' == 0 is true. This is because when using == to compare a string and a number, the string is converted to a number (as described in the second link below); this makes the comparison internally become 0 == 0 which is of course true.
The suggested alternative for your needs, would be to use a strict equality comparison using ===.
See Comparison Operators and String conversion to numbers
In PHP, when you compare 2 types, it has to convert them to the same type. In your case, you compare string with int.
Internally this gets converted to
if((int)'van'==0)....
and then
if((int)'van'==1)....
(int)'any possible string' will be 0:) So you either have to manually convert the both values to the same type, or use === as a comparison operator, instead of the loose =.
An exception from this rule(as pointed out in the comments) would be if the string start with a number, or can be interpreted as a number in any way(1, 0002, -1 etc). In this case, the string would be interpreted as a number, diregarding the end of the non-numeric end-of-string
Take a look at http://php.net/manual/en/types.comparisons.php for more details.
This works fine:
$array = array(0=>"a",1=>"b","van"=>"booya!");
function p($v){ echo "{$v}<br />"; }
foreach ($array as $k => $reqInfo)
{
p($k);
if ('van' === $k) { p('The key is the van, continue'); continue; }//continue if we reached the part of the array where van is key
//do stuff
}
Output:
0
1
van
The key is the van, continue
Note the ===.
Read the Comparison with Various Types table
When one of the operand is number, the other operand is converted to number too. Since 'van' is non-numeric sting, it's converted to 0. You should use === operator in the case, which also checks the variable type
That's becuase 'van' == 0 (true).
Instead, you should use 'van' === 0 (false).
In short, use === instead of ==.
Its interpreting the 'van' as a boolean value (false) which 0 is equal to.
To check for exact matches in type and value in PHP you must use === instead of ==

Categories