2011-01-04 6 views
2

Я давно использовал назначение в операторах long if для упрощения. Но в этом случае он не работает должным образом. Вот что я получил:Если оператор дает неправильный ответ

$Employee = GetEmployeeName($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']))); 

Вот результаты:

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) 

Это не имеет никакого смысла. Сравнение первого имени разрешается как 0 (false); сравнение последнего имени разрешается как 0 (false); сравнивая их вместе, разрешается как ложное. Однако, когда я добавляю назначение в if, он внезапно решается как истинный. Я назначал переменные в ifs в течение длительного времени, и я никогда не видел, чтобы это произошло. Странно, если я назначаю вне if, то он отлично работает. Поэтому я мог бы это сделать, но на данный момент речь идет о принципе выяснения того, что происходит не так, поэтому я могу улучшить свои знания языка.

Присвоение в этом случае дает истину, как вы можете видеть из-за того, что заполняется $ Employee. Итак, окончательный var_dump по существу является «true & & false», который должен быть разрешен как false. Правильно?

+0

Нет, окончательный 'var_dump()' демпинг значение 'только $ Foo'. – BoltClock

+1

Я подозреваю, что здесь есть проблемы с выбором типа. Помните, что strcasecmp() не возвращает bool, а int. То, что вы должны попробовать, это нечто вроде '(strcasecmp ($ Employee ['first_name'], $ Record ['first_name']) == 0)', так что вы преобразовываете вывод strcasecmp() в значение bool, соответствующее дальнейшее сравнение позже. – Brad

+0

Я знаю, что он возвращает int, но когда они равны, он возвращает 0, который разрешает false. :) – Andrew

ответ

4

Оператор boolean && имеет номер precedence, отличный от оператора присваивания =. Так что это:

$Foo = GetEmployeeName($Record['employee_id']) 
    && (strcasecmp($Foo['first_name'], $Record['first_name']) 
     || strcasecmp($Foo['last_name'], $Record['last_name'])) 

эквивалентно:

$Foo = (GetEmployeeName($Record['employee_id']) 
    && (strcasecmp($Foo['first_name'], $Record['first_name']) 
     || strcasecmp($Foo['last_name'], $Record['last_name']))) 

Поместите круглые скобки вокруг присваивания, и она работает:

($Foo = GetEmployeeName($Record['employee_id'])) 
    && (strcasecmp($Foo['first_name'], $Record['first_name']) 
     || strcasecmp($Foo['last_name'], $Record['last_name'])) 
+0

Сын gumble. Проверьте мою историю вопроса; Раньше я был замешан в приоритете оператора. Но, согласно документации PHP, «хотя = имеет более низкий приоритет, чем большинство других операторов, PHP все равно позволит выражениям, аналогичным следующим: if (! $ A = foo()), и в этом случае возвращаемое значение foo () помещается в $ a. «Каковы логические пределы этого? Они не вдаются в подробности относительно того, какие выражения elevate = 's приоритет. – Andrew

+0

@Gumbo Я немного смущен, почему это не оценивается как '$ Foo = true && (false || false)', который, очевидно, возвращает false. Не могли бы вы объяснить, что я пропустил здесь? – lonesomeday

+0

@lonesomeday: из-за приоритета оператора ('&&' имеет более высокий приоритет, чем '=', поэтому логическая операция И выполняется перед операцией присваивания) выражение '$ Foo = true && (false || false)' равно эквивалентно '$ Foo = (true && (false || false))'. – Gumbo

0

из-за operator precedence, ваш код интерпретируется следующим образом:

сначала результат:

GetEmployeeName($Record['employee_id']) && (strcasecmp($Foo['first_name'], 
$Record['first_name']) || strcasecmp($Foo['last_name'], 
$Record['last_name'])) 

если проверено

после этого результата asignet к $Foo - и if просто проверяет, является ли это назначение было успешным.

Чтобы избежать этого, используйте фигурные скобки для правильной группировки частей вашего camparision.

+0

Для точности, '&&' имеет более высокий приоритет, чем '==', но 'и' нет. [См. Руководство] (http://php.net/manual/en/language.operators.precedence.php) – lonesomeday

+0

@lonesomeday: спасибо за подсказку, я только что увидел это и перефразировал свой ответ;) – oezi

-1

strcasecmp:

< Возвращает 0, если str1 меньше, чем str2; > 0, если str1 больше str2 и 0, если они равны.

поэтому возвращение нуля означает, что они равны друг другу не ложно

// Это форма пример кода сам PHP сайт

<?php 
    $var1 = "Hello"; 
    $var2 = "hello"; 
    if (strcasecmp($var1, $var2) == 0) { 
     echo '$var1 is equal to $var2 in a case-insensitive string comparison'; 
    } 
?> 

Как заявили в комментариях выше, они должны возвращать те же результаты. Пожалуйста, выполните пример кода, и вы увидите, что нет.

<?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 

?> 

Как вы используете var_dump для сравнения Int (0) возвращает возвращает логическое значение (ложь)

// 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"))); 
+0

И 0 означает false , В этом случае равно false. Но это не то, о чем я говорил. – Andrew

+0

В документации по PHP указано, что ZERO означает равные друг другу NOT FALSE –

+0

И в документации по PHP также указывается, что '(bool) 0 === false'. – Andrew

1

Я только что провел ярмарку в то время как выяснить проблемы с этим, и наконец, попали в проблему.

Мой тестовый код:

var_dump($Foo = array('first_name' => 'ZACHARY', 'last_name' => 'TAYLOR') 
    && (strcasecmp($Foo['first_name'], 'Zachary') 
     || strcasecmp($Foo['last_name'], 'Taylor'))); 

дает выход:

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) 

Проблема заключается в том, что $Foo назначается лишь после того, как все действие на право оператора = произошло. Поэтому, когда вы звоните strcasecmp($Foo['first_name'], 'Zachary'), вы на самом деле делаете strcasecmp('', 'Zachary'), что составляет -7 (boolean true). Поэтому ваш код оценивается следующим образом:

$Foo = true && (-7 || -7); 

Это, очевидно, так.

Как показано в другом месте, то решение положить $Foo в скобках, так что сначала вычисляется:

var_dump(($Foo = array('first_name' => 'ZACHARY', 'last_name' => 'TAYLOR')) 
    && (strcasecmp($Foo['first_name'], 'Zachary') 
     || strcasecmp($Foo['last_name'], 'Taylor'))); 
+0

Aha! Спасибо, что поняли, что нас сбило с толку. – Andrew

Смежные вопросы