I encountered a code line that looks like this:
if ($users == 'all' || $_POST['user'] == 1 && $users == 'admins' || $_POST[ 'user' ] == 0 && $users == 'mods') ...
I don't understand how are all these conditions met because there are not parentheses between them :(
Is ||
more important than &&
? Which parts get evaluated first?
Best Answer
&&
depends of the evaluation of the right expression when left one is true, ||
doesn't. You could rewrite it to:
if($users == 'all' ||($_POST['user'] == 1 && $users == 'admins') ||($_POST['user'] == 0 && $users == 'mods'))
And it'll be the same.
With no parenthesis, PHP will evaluate each expression from left to right, using PHP's operator precedence along the way. However, as in any logical check, throwing AND
into the mix can make things confusing and a lot harder to read.
It starts out going from left to right unless precedence takes over.
function rtrue($x) {static $rt = 0;echo $x . ' called true ' . ++$rt . '<br>';return true;}function rfalse($x) {static $rf = 0;echo $x . ' called false ' . ++$rf . '<br>';return false;}// all but last get called, eq: false || (true && false) || (false && true)$result1 = rfalse('a') || rtrue('b') && rfalse('c') || rfalse('d') && rtrue('e');echo '=== result '. ( $result1 ? 'true' : 'false' ) . '<br>';// first true does not get called, eq: (false && true) || true$result2 = rfalse('x') && rtrue('y') || rtrue('z');echo '=== result '. ( $result2 ? 'true' : 'false' ) . '<br>';
Prints the following:
a called false 1b called true 1c called false 2d called false 3=== result falsex called false 4z called true 2=== result true
You can see the same behavior in a JavaScript snippet too:
var rt = 0;function rtrue(x) {console.log(x, 'called true', ++rt);return true;}var rf = 0;function rfalse(x) {console.log(x, 'called false', ++rf);return false;}// all but last get called, eq: false || (true && false) || (false && true)console.log('=== result',rfalse('a') || rtrue('b') && rfalse('c') || rfalse('d') && rtrue('e'));// first true does not get called, eq: (false && true) || trueconsole.log('=== result',rfalse('x') && rtrue('y') || rtrue('z'));