PHP returns true for strings and non-zero numbers as true

If you do:

$string = 'foo';

if($string) {

   echo 'I am true';

}

It will echo I am true. The same goes for all numbers other than 0, ‘0’, 0.0, etc.

Why is this? I find it confusing when you cast a string as a bool and it returns true. I’d expect anything other than true, 1 and ‘1’ to cast to false.

With this in mind, I’m considering coding if($var === true) instead of if($var). It just seems more readable and watertight.

Thoughts?

I think this behaviour is consistent with what is considered true in other languages. Usually, anything other than 0, false, null or empty string is considered true. Compare it to MySQL - any number other than 0 or NULL is considered true (strings are different because they are not really convertible to booleans there). To me how php works in this case makes sense - of course, this is subjective and other people may find some of the behaviour illogical but at least it is to some extent compatible with other languages so there’s no need to switch to a completely different definition of what is true or false.

And as to the string ‘0’ being false - I think the reason for this is because it allows for quite logical handling of values from databases. In php all values from a database usually arrive as strings so this way if you have a boolean 0 in the db it will be naturally treated as false in php without any conversions. Take MySQL as an example where you want to store a boolean true/false:

  1. The most natural data type for boolean is TINYINT where you store 0 or 1. Why? Because there is no real boolean type and 0/1 have traditionally been used as false/true in most languages - and even MySQL has keywords TRUE and FALSE, which equal to numbers 1 and 0.

  2. You fetch this ala-boolean TINYINT value in php and you get a string ‘0’ or ‘1’ - and you can do boolean comparisons straight away because php interprets ‘0’ as false.

Yes, if($var === true) is more watertight and if it makes things clearer to you then use it. Personally, I don’t find if($var) difficult to read but of course I need to be aware that if($var) allows for many more values than if($var === true) - however, there are cases when being so watertight is not necessary at all so I just go for the shorter version.

Edit:

One more thing came to my mind - because of the nature of php (being a dynamically typed language) I feel that we shouldn’t do strict comparisons (===) where not really necessary. Most built-in php functions and methods do not require one specific type for their arguments - you can feed them other types as long as they can be converted to their target types. For example:


curl_setopt($ch, CURLOPT_HEADER, false);

The last argument is a boolean true or false value. However, if you provide other values that can be converted to a boolean then things will works just the same:


curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_HEADER, '0');
curl_setopt($ch, CURLOPT_HEADER, null);
curl_setopt($ch, CURLOPT_HEADER, '');

The same goes for strings, integers and floats - if a function expects any of these you can usually use any of the other types without a problem. That’s why I think to be consistent with the nature of php strict comparisons should be avoided in cases where they are not necessary. For example, when checking for boolean true/false this is too strict:

if ($var === true);

but any of these will be more appropriate:


if ($var);
if ($var == true);

I know some people may disagree with me but I am of the opinion that we shouldn’t try to make php a different language than it actually is. Type juggling is a natural characteristics of php and we shouldn’t try to supress it by using too strict comparisons. Both strict and loose comparisons have their pros and cons but to me it’s more important to be consistent - if almost all php functions use loose comparisons then I don’t see a reason why my own functions would use strict comparisons.

Thanks for the detailed reply, all very interesting. I’m questioning myself now. To me a more logical bool casting function would be:

function bool($var) {

    if($var == '1') {
        return true;
    }
    else {
        return false;
    }

}

Also, is if($var === true) really too strict? I mean that as in, is it more computationally expensive? Although there are some merits to being loosely typed I think less ambiguous, more readable code is a good thing? For example, I think using the PHP shorthand where you omit the braces is a bad idea.

Yes, you could do it but my point is that because php is loosely typed there is no need for this bool casting function at all if you don’t use strict comparisons.

Actually, the strict comparisons are computationally less expensive (but very slightly). And by saying “too strict” I don’t mean it’s too strict in itself and I don’t mean it’s wrong. To me it’s just inconsistent with how php works. Almost all built-in php code is not strict so I don’t see a reason to make my code strict. If all php functions will accept strings, numbers, floats (and even arrays) as booleans then I will make my own function follow the pattern. And it’s easily done just by not using strict comparisons in cases when loose comparisons will do just fine.

My response to your response would be: “Why is ‘true’ false?”

Less ambiguous, more readable code is a good thing. So dont use if($var). Because it’s ambiguous and less readable. :wink:

Do you mean the string ‘true’? Or just true (because true == ‘1’). My point is that to me 1 or true (and yes maybe the string 'true;)is true and everything else should default to false. If I cast something like ‘ertyrhgfdhtgh’ to me that is nothing even close to true so therefore it’s false.

I appreciate Lemon Juice’s point about other languages though. I don’t know though, maybe my mind works in a weird way but to me this seems more logical

function bool($var) {

    if($var == '1' || $var === 'true') {
        return true;
    }
    else {
        return false;
    }

}

It’s more just the logic is inverted from PHP’s perspective (or more to the point, you’re testing for the opposite conditions).

You say: If it’s X or Y, it’s true, otherwise it’s false.
PHP says: If it’s X or Y, it’s false, otherwise it’s true.

PHP thinks an array with no elements is False. But it’s still an object that exists.

So you basically have your own definition of what is true that is different from what php says. There is no problem with your definition except it is non-standard. You can apply your definition to your code and it will work but I believe it’s better practice to stick to standards - this helps us all and the code is more readable to other people because they don’t have to learn what true means to you. So your function that casts to boolean could be as simple as this, if you stick to the standard:

function bool($var) {
    return (bool) $var;
}

which is so simple that in actual fact you don’t need a function for that :slight_smile:

According to your logic you want a string ‘1’ to be true but other strings to be false.
Ok, so what’s so special about the ‘1’? when ‘1’ is true but ‘2’ is false? They both strings, right. Also this logic will make a string ‘true’ to be false.

Basically you are questioning the logic of the language that has been in the language forever.
I think a better approach is to accept the rules of the language and use it. What do you think would happen if php designers were to agree with you and change the existing logic?

I know, I know, you’re both right. It’s been a useful learning exercise though!