El comportamiento del operador or en PHP
Estoy tratando de entender el comportamiento del operador or
. Por favor vea los siguientes ejemplos:
$e = false || true;
var_dump($e);
La salida es la esperada: bool(true);
$f = false or true;
var_dump($f);
La salida es la esperada: bool(false)
. Entendí esto de una manera que el =
tiene una precedencia más alta que el Or
, por lo que el $f
se asigna a false
.
Pero el siguiente código funciona bastante opuesto a lo que pensé. Pensé que el $foo
será asignado a 5
y luego comparado consigo mismo.
Pero el $foo
es obtener asignado solo cuando si el $foo
está establecido eso significa que está comprobando si el $foo
está asignado a algo anterior, asígnele 5.
$foo or $foo = 5;
¿Puede alguien explicar por qué esto es así?
4 answers
Lo básico:
-
Una expresión de asignación da como resultado el valor asignado.
¿Qué significa eso?
$foo = 'bar'
es una expresión en la que el operador de asignación=
asigna un valor. Una expresión siempre devuelve un valor. Al igual que la expresión1 + 2
resulta en el valor3
, la expresión$foo = 'bar'
resulta en el valor'bar'
. Es por eso que esto funciona:$foo = $bar = 'baz'; // which is: $foo = ($bar = 'baz');
Las operaciones booleanas son operaciones de cortocircuito. Ambos lados no son siempre se evalúan si no es necesario.
true || false
es siempretrue
en general, ya que el operando izquierdo estrue
, por lo que toda la expresión debe sertrue
.false
ni siquiera está siendo evaluado aquí.La precedencia del operador dicta en qué orden las partes de una expresión se agrupan en subexpresiones. Los operadores de mayor precedencia se agrupan con sus operandos antes de la precedencia inferior operador.
Por lo tanto: {[44]]}
$e = false || true;
false || true
se está evaluando, lo que da como resultado el valor true
, que se asigna a $e
. El operador ||
tiene una precedencia mayor que =
, por lo tanto false || true
se agrupa en una expresión (a diferencia de ($e = false) || true
).
$f = false or true;
Aquí ahora or
tiene una precedencia inferior que =
, lo que significa que la operación de asignación se agrupa en una expresión antes de or
. Así que primero el $f = false
se evalúa la expresión, cuyo resultado es false
(ver arriba). Entonces tenemos la expresión simple false or true
que se evalúa a continuación y resulta en true
, pero que a nadie le importa.
La evaluación funciona así: {[44]]}
1. $f = false or true;
2. ($f = false) or true; // precedence grouping
3. false or true; // evaluation of left side ($f is now false)
4. true; // result
Ahora:
$foo or $foo = 5;
Aquí, de nuevo, $foo = 5
tiene una precedencia más alta y se trata como una sola expresión. Dado que ocurre en el lado derecho del operador or
, la expresión solo se evalúa si es necesario. Depende de lo que $foo
es inicialmente. Si $foo
es true
, el lado derecho no se evaluará en absoluto, ya que true or ($foo = 5)
debe ser true
en general. Si $foo
tiene un valor falsey inicialmente, sin embargo, se evalúa el lado derecho y 5
se asigna a $foo
, lo que resulta en 5
, que es true-ish, lo que significa que la expresión general es true
, que a nadie le importa.
1. $foo or $foo = 5;
2. $foo or ($foo = 5); // precedence grouping
3. false or ($foo = 5); // evaluation of left side
4. false or 5; // evaluation of right side ($foo is now 5)
5. true; // result
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-04 08:58:06
Según el php.net página web sobre Operadores lógicos :
Esto:
$e = false || true;
Actúa así: {[16]]}
$e = (false || true) // If false is true, then $e = false. Otherwise true
Esto:
$f = false or true;
Actuaría así:
($f = false) or true; // $f = false is true, as the assignment succeeded
Esto:
$foo or $foo = 5;
Actuaría así:
$foo or ($foo = 5) // foo = undefined or foo = 5, so foo = 5
Para el último, undefined es básicamente como false, por lo tanto foo es igual a 5.
También, aquí está el enlace para el orden de precedencia del operador: http://www.php.net/manual/en/language.operators.precedence.php
ACTUALIZACIÓN:
Ok, ahora vamos al punto principal. Al igual que todos sabemos cuando se utiliza una consulta obtenida:
while($row = @mysql_fetch_assoc($result))
Y todos sabemos que los bucles while solo se ejecutan en true
, por lo tanto $row = @mysql_fetch_assoc($result)
devuelve true.
Lo mismo con la pregunta de Daric.
$foo or $foo = 5;
Es básicamente:
$foo or ($foo = 5);
Que es básicamente:
$foo = undefined or ($foo = 5); // $foo = 5 actually returns true
Que es también
$foo = undefined or true;
Y como he anteriormente mencionado, undefined = false, por lo tanto fo foo = 5 (como esa es la declaración verdadera).
Espero que todos puedan entender.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-31 11:24:30
$foo or $foo = 5;
Suppose let say $foo=true or $foo=5;
Aquí no se evaluará después o la expresión del operador, por lo que la salida será fo foo = 1 Ahora la expresión es
$foo=false or $foo=5;
Aquí se evaluará después o como = mayor precedencia so $foo
a partir de cuál de los cuales se evaluará $foo=5
so salida será 5
Pero cuando evaluamos $foo=false or true
así que aquí se considerará = mayor precedencia por lo que la salida será $foo=false
pero toda la expresión se evaluará como verdadera porque false or true
se convierte en false
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-05 04:37:50
<?php
$foo = false;
$foo or ($foo = '5');
echo $foo;
?>
Marque esto puede asignar el valor "5" para $foo
.
Comparar que or
=
tiene alta prioridad.. Ese es el hecho.... :)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-31 10:25:36