If statement giving a wrong answer
I've long used assignment inside long if statements to simplify things. But in this case, it's not working as intended. Here's what I've got:
$Employee = GetEmployee开发者_开发百科Name($Record['employee_id']);
echo 'First name: '.$Employee['first_name'];
echo 'Last name: '.$Employee['last_name'];
echo 'Record first name: '.$Record['first_name'];
echo 'Record last name: '.$Record['last_name'];
echo 'Comparing first name: ';
var_dump(strcasecmp($Employee['first_name'], $Record['first_name']));
echo 'Comparing last name: ';
var_dump(strcasecmp($Employee['last_name'], $Record['last_name']));
echo 'Comparing both together: ';
var_dump(strcasecmp($Employee['first_name'], $Record['first_name'])
|| strcasecmp($Employee['last_name'], $Record['last_name']));
echo 'All together now: ';
var_dump($Foo = GetEmployeeName($Record['employee_id'])
&& (strcasecmp($Foo['first_name'], $Record['first_name'])
|| strcasecmp($Foo['last_name'], $Record['last_name'])));
Here's the results:
First name: ZACHARY
Last name: TAYLOR
Record first name: Zachary
Record last name: Taylor
Comparing first name: int(0)
Comparing last name: int(0)
Comparing both together: bool(false)
All together now: bool(true)
This makes no sense. Comparing the first name resolves as 0 (false); comparing the last name resolves as 0 (false); comparing them together resolves as false. Yet when I add the assignment into the if, it suddenly resolves as true. I've been assigning variables in ifs for a long time and I've never seen this happen. The weird thing is, if I assign outside the if, it works fine. So I could do that, but at this point it's about the principle of finding out what's going wrong so I can improve my knowledge of the language.
Assignment in this case gives true, as you can see by the fact that $Employee is populated. So, the final var_dump
is essentially "true && false", which should resolve as false. Right?
The boolean operator &&
has a higher precedence than the assignment operator =
. So this:
$Foo = GetEmployeeName($Record['employee_id'])
&& (strcasecmp($Foo['first_name'], $Record['first_name'])
|| strcasecmp($Foo['last_name'], $Record['last_name']))
Is equivalent to:
$Foo = (GetEmployeeName($Record['employee_id'])
&& (strcasecmp($Foo['first_name'], $Record['first_name'])
|| strcasecmp($Foo['last_name'], $Record['last_name'])))
Put the parentheses around the assignment and it works:
($Foo = GetEmployeeName($Record['employee_id']))
&& (strcasecmp($Foo['first_name'], $Record['first_name'])
|| strcasecmp($Foo['last_name'], $Record['last_name']))
I've just spent a fair while figuring out the problem with this, and have finally hit on the problem.
My test code:
var_dump($Foo = array('first_name' => 'ZACHARY', 'last_name' => 'TAYLOR')
&& (strcasecmp($Foo['first_name'], 'Zachary')
|| strcasecmp($Foo['last_name'], 'Taylor')));
Gives the output:
PHP Notice: Undefined variable: Foo in /home/sam/test.php on line 6
PHP Stack trace:
PHP 1. {main}() /home/lday/test.php:0
bool(true)
The problem is that $Foo
is only assigned after all the action on the right of the =
operator has happened. So when you call strcasecmp($Foo['first_name'], 'Zachary')
, you are actually doing strcasecmp('', 'Zachary')
, which evaluates to -7
(boolean true
). So your code evaluates like this:
$Foo = true && (-7 || -7);
Which is obviously true.
As shown elsewhere, the solution is to put $Foo
in brackets, so it is evaluated first:
var_dump(($Foo = array('first_name' => 'ZACHARY', 'last_name' => 'TAYLOR'))
&& (strcasecmp($Foo['first_name'], 'Zachary')
|| strcasecmp($Foo['last_name'], 'Taylor')));
because of the operator precedence, your code is interpreted as follows:
first, the result of:
GetEmployeeName($Record['employee_id']) && (strcasecmp($Foo['first_name'],
$Record['first_name']) || strcasecmp($Foo['last_name'],
$Record['last_name']))
if checked
after this the result is asignet to $Foo
- and if
just checks if this assignment was successful.
to avoid this, use braces to group the parts of your camparision correctly.
strcasecmp :
Returns < 0 if str1 is less than str2; > 0 if str1 is greater than str2, and 0 if they are equal.
so the return of zero means they equal each other not false
// This is the example code form the PHP site itself
<?php
$var1 = "Hello";
$var2 = "hello";
if (strcasecmp($var1, $var2) == 0) {
echo '$var1 is equal to $var2 in a case-insensitive string comparison';
}
?>
As you have stated in your comments above, these should both return the same results. Please execute the example code and you will see they do not.
<?php
if(strcasecmp("ZACHARY", "Zachary") == 0) {
echo "We have a match with a zero (int) return\n"; // this returns 0
}
echo !strcasecmp("ZACHARY", "Zachary")."\n"; // this will return 1
?>
How you're using var_dump to compare int(0) returns will return a bool(false)
// returns int(0)
var_dump(strcasecmp("ZACHARY", "Zachary"));
// will return bool(false) as it's comparing int(0) || int(0)
var_dump((strcasecmp("ZACHARY", "Zachary")) || (strcasecmp("ZACHARY", "Zachary")));
精彩评论