bwright
bwright

Reputation: 347

Comparing BOOLEAN TRUE to INTEGER value in PHP

I have the following PHP (the server is running version 5.3.x) in a script which is giving me a result that I am having trouble understanding. The general idea of this code is that I have a "normal mode", and two maintenance modes. In the first maintenance mode, data is only evaluated and can be viewed by an admin but is not stored to the database. If I set $maintenance_mode_enabled = 2;, then the same "preview" output should be displayed but only SOME specific updates to the database should be processed. The reason I added the ==2 comparison is because I found the need for a third option after I had setup the true/false for the basic default maintenance mode. At any rate, I noticed 18 records on my last maintenance_mode_enabled = true; run that were partially updated during the process, just as though I had set maintenance_mode_enabled = 2;.

        $maintenance_mode_enabled = true;

        if ($maintenance_mode_enabled){
            echo "Case 0\n";
        }

        if (!$maintenance_mode_enabled){
            echo "Case 1\n";
        }

        if ($maintenance_mode_enabled == 2){
            echo "Case 2\n";
        }

The output I get is:

Case 0
Case 2

From what I understood, true (being boolean) is definitely not equal to 3. I am familiar with some oddities when comparing false, NULL and 0, but this problem with integers and TRUE is entirely new to me.

Any ideas as to why this isn't working? I realize that I can just as easily change $maintenance_mode_enabled to an integer instead of a bolean by default, and set it as either 0, 1 or 2 to get the desired results, but I really want to understand WHY this seems to defy logic.

Upvotes: 1

Views: 2594

Answers (3)

nmallare
nmallare

Reputation: 97

The reason this happens is because you're comparing a boolean to an integer. As with many languages, at the core of the comparison function it's casting the second part of your comparison to a boolean. Any non-NULL, non-zero, non-empty or non-false value, in this case 2 is "true."

As the previous answer mentions I would change the code to use strict comparison. I would also change from three separate if-statements to one if-elseif statement:

if ($maintenance_mode_enabled === true) {
    // catches only true not > 0
    echo "Case 0\n";
} elseif ($maintenance_mode_enabled === false) {
    // catches only true not = 0
    echo "Case 1\n";
} elseif ((int)$maintenance_mode_enabled === 2) {
    echo "Case 2\n";
}

I recommend this change because maintenance mode can only have one value.

EDIT

I didn't realize true and 2 could coexist. You could do:

if ($maintenance_mode_enabled) {
    echo "Case 0\n";
    if (2 === (int)$maintenance_mode_enabled) {
        echo "Case 2\n";
    }
} else {
    echo "Case 1\n";
}

Upvotes: 4

mseifert
mseifert

Reputation: 5670

Use the === operator for true otherwise all non 0 / null / false will be true.

Use the === operator for false otherwise all equal to 0 / false / null will show as "false"

The following will output Case 0

<?php 
 $maintenance_mode_enabled = true;
 if ($maintenance_mode_enabled === true){
        // catches only true not just > 0
        echo "Case 0\n";
    }

    elseif (!$maintenance_mode_enabled === false){
        // catches only false not including = 0
        echo "Case 1\n";
    }
    elseif ($maintenance_mode_enabled == 2){
        echo "Case 2\n";
    }

?>

Upvotes: 1

bwright
bwright

Reputation: 347

Oh, NOW I get it. It seems the problem here is that when I do the loose (==) comparison of a boolean with an integer, the type casting is converting the integer into a boolean, thus resulting in 2 being equal to true - since both are being tested as booleans. The solution is to use strict (===) comparison, so that both must be of the same type... i.e.: 2 (integer), is not exactly the same as true, since true is is of a different type - boolean.

Upvotes: 0

Related Questions