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:
-
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.
-
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.