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

Author: leppie, 2012-08-31

4 answers

Lo básico:

  1. 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ón 1 + 2 resulta en el valor 3, la expresión $foo = 'bar' resulta en el valor 'bar'. Es por eso que esto funciona:

    $foo = $bar = 'baz'; // which is: $foo = ($bar = 'baz');
    
  2. Las operaciones booleanas son operaciones de cortocircuito. Ambos lados no son siempre se evalúan si no es necesario. true || false es siempre true en general, ya que el operando izquierdo es true, por lo que toda la expresión debe ser true. false ni siquiera está siendo evaluado aquí.

  3. 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
 52
Author: deceze,
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.

 24
Author: think123,
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

 5
Author: Arpit Srivastava,
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.... :)

 4
Author: Basith,
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