6 Replies - 361 Views - Last Post: 06 August 2013 - 04:17 PM Rate Topic: -----

#1 djdave106  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 6
  • Joined: 22-March 12

logically inequivalent statements in PHP

Posted 12 July 2013 - 11:34 PM

I am stumped by a gap in my understanding of logical expressions. I have code that decides whether to display a button, based on a compound logical expression. My original code was like this:

$bShowButton = <logical expr>;



However, this did not work. I was a long time examining the components of the expression, only to find they all behaved as I expected, and that this formulation:

$bShowButton = false;
if (<logical expr>) $bShowButton = true;



worked fine, so the logical expression I thought must be wrong was actually right. However, I don't understand why the two bits of code yield different outcomes (the first always yields true). Can anyone explain? For the record here is my actual expression, although I think it is irrelevant:

        $bShowButton = ($dtmCurrentSlotTime >= $dtmLaunchDate) And ($bIsAdmin Or !$bSlotNotAvailable) And (!$bBlockedOut) Or ($bAdminBlockOutMode And !$bBlockedOut);
        $bShowButton = false;
        if (($dtmCurrentSlotTime >= $dtmLaunchDate) And ($bIsAdmin Or !$bSlotNotAvailable) And (!$bBlockedOut) Or ($bAdminBlockOutMode And !$bBlockedOut)) $bShowButton = true;



Is This A Good Question/Topic? 0
  • +

Replies To: logically inequivalent statements in PHP

#2 Dormilich  Icon User is offline

  • 痛覚残留
  • member icon

Reputation: 3530
  • View blog
  • Posts: 10,180
  • Joined: 08-June 10

Re: logically inequivalent statements in PHP

Posted 13 July 2013 - 03:04 AM

Im not having any problems with

View Postdjdave106, on 13 July 2013 - 08:34 AM, said:

$bShowButton = <logical expr>;


example:
$ex = (1 > 2) and true;
var_dump($ex); // bool(false)



View Postdjdave106, on 13 July 2013 - 08:34 AM, said:

For the record here is my actual expression, although I think it is irrelevant:

        $bShowButton = ($dtmCurrentSlotTime >= $dtmLaunchDate) And ($bIsAdmin Or !$bSlotNotAvailable) And (!$bBlockedOut) Or ($bAdminBlockOutMode And !$bBlockedOut);
        $bShowButton = false;
        if (($dtmCurrentSlotTime >= $dtmLaunchDate) And ($bIsAdmin Or !$bSlotNotAvailable) And (!$bBlockedOut) Or ($bAdminBlockOutMode And !$bBlockedOut)) $bShowButton = true;


this particular code is hard to test without knowing what the variables are and what values you get. However, it is to be noted that AND and OR have a different operator precedence.
Was This Post Helpful? 0
  • +
  • -

#3 CTphpnwb  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 2960
  • View blog
  • Posts: 10,186
  • Joined: 08-August 08

Re: logically inequivalent statements in PHP

Posted 13 July 2013 - 06:34 AM

Build your code one step at a time. For example, does this produce what you would expect?
$bShowButton = ($dtmCurrentSlotTime >= $dtmLaunchDate);

How about this?
$bShowButton = ($bIsAdmin Or !$bSlotNotAvailable));

If they both work properly, put them together:
$bShowButton = ($dtmCurrentSlotTime >= $dtmLaunchDate) And ($bIsAdmin Or !$bSlotNotAvailable);

If that works, continue building your test. If not, fix it before moving on.

This post has been edited by CTphpnwb: 13 July 2013 - 06:35 AM

Was This Post Helpful? 0
  • +
  • -

#4 djdave106  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 6
  • Joined: 22-March 12

Re: logically inequivalent statements in PHP

Posted 05 August 2013 - 02:02 AM

the problem was that 'Or' has lower precedence than '=', so

logical_var = A Or B



was setting logical_var to A
Was This Post Helpful? 0
  • +
  • -

#5 CTphpnwb  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 2960
  • View blog
  • Posts: 10,186
  • Joined: 08-August 08

Re: logically inequivalent statements in PHP

Posted 05 August 2013 - 03:36 AM

The problem is that '=' is not a comparison. It's an assignment operator. Use '==', as in: if(x == y) {
Was This Post Helpful? 0
  • +
  • -

#6 AdaHacker  Icon User is offline

  • Resident Curmudgeon

Reputation: 452
  • View blog
  • Posts: 811
  • Joined: 17-June 08

Re: logically inequivalent statements in PHP

Posted 06 August 2013 - 03:23 PM

View PostCTphpnwb, on 05 August 2013 - 06:36 AM, said:

The problem is that '=' is not a comparison. It's an assignment operator. Use '==', as in: if(x == y) {

You didn't read the expression very closely, did you? :) It doesn't contain any equality comparisons.

No, djdave106 is actually correct. Counter-intuitive as it is, the or operator actually has lower precedence than the assignment operator. Consider this example:
$a = false;
$b = true; 
$c = $a or $b;
var_dump($c);  // prints "bool(false)"


This is why using the and and or operators is almost always a bad idea. The precedence is so weirdly low that it's very easy to get the wrong behavior. For typical logical expressions, && and || are more in line with what you'd usually expect.
Was This Post Helpful? 1
  • +
  • -

#7 Atli  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 3718
  • View blog
  • Posts: 5,989
  • Joined: 08-June 10

Re: logically inequivalent statements in PHP

Posted 06 August 2013 - 04:17 PM

View PostAdaHacker, on 06 August 2013 - 11:23 PM, said:

Counter-intuitive as it is, the or operator actually has lower precedence than the assignment operator.

I wouldn't exactly call it counter intuitive. The fact that the or operator has lower precedence can actually be useful, and it was no doubt set up for this very reason. - It means that it can be used to evaluate values after they have been assigned in an expression, rather than before they would be, as is the case with ||.

Consider this:
function foo($i) {
    return $i % 2 === 0;
}

if ($x = foo(1) || $y = foo(2));


The intent here - as somebody without intimate knowledge of PHP operator precedence would guess - is that $x and $y be set to their respective foo result values, and then compared using the || operator.

However, because the || has higher precedence than =, the grouping essentially becomes:
if ($x = (foo(1) || ($y = foo(2) ) ) );


Leaving $x to alwasy mirror $y, and the outcome of the expression to always be determined by the second foo call. (True, in this case.)

The or operator solves this neatly by letting the assignment happen first, and then be compared. The grouping becomes what the initial thinking suggested:
if ( ($x = foo(1)) or ($y = foo(2)) );



Of course, this is just a hypothetical. In reality you should neither be assigning variables inside the condition, nor be leaving them at the mercy of PHP's operator precedence. (Parenthesis. Learn to love it!) - The reason behind that becomes clear if you switch the input values for the foo functions in that second example. As the first foo call is true, the second call doesn't have to be executed (the truthfulness of the statement has already been determined by the first; no reason to do the second as well), so $y is never assigned. Unless you're anticipating that $y not be set if $x turns out to be true, this is hardly ideal behavior.
Was This Post Helpful? 1
  • +
  • -

Page 1 of 1