"0", as a string containing one character, is not something empty intuitively. Why does PHP treat it as FALSE when converted to a boolean, unlike other programming languages?
PHP was designed (or, rather, evolved) for use with web requests, where you're frequently dealing with string input (URL parameters, or POST requests from a form in a browser). As such, it will automatically cast strings to other types.
A simple example of this is that
'1' + '2' gives
3, not an error, or
'12', or some other interpretation. By the same logic, the string
'0' can be used as a numeric
Meanwhile, like many languages, PHP treats certain values as "falsy" when cast to boolean - things that are intuitively "empty", as you say. That includes numeric
0, as well as the empty string
'' and the empty array
. In an
if statement, the expression is explicitly cast to boolean, so
if ( 0 ) is the same as
if ( false ).
Putting these two things together, you get a conundrum: on the one hand, as you say
'0' is a non-empty string; on the other hand, we have said that it can be used as a numeric
0, which is "empty". PHP opts to treat the "zero-ness" as more important than the "stringiness", so that
'0' is considered "falsy".
'0' == 0 == false; or
(bool)'0' === (bool)(int)'0'
Did somebody downvote my answer just because I dared to defend PHP and answer the question with something other than a cheap and ignorant joke? Or is there something inaccurate or unhelpful in my answer that they would like to point out? Dec 19, 2016 at 12:03
1I think PHP took this from Perl, which has the same “
"0"is false” behaviour. In Perl, there literally isn't any user-visible difference between the string
0– annoying when handling JSON, but very intuitive when handling textual data. It is then impossible to have the number
0be falsey without also the string
0 == "0 foo",
0 == false, but
"0 foo" == true:
==isn't transitive)– amonDec 19, 2016 at 12:49
@amon Yes, Perl takes the interesting approach of (nearly) all operators and built-in functions forcing operands to a particular type, with extra operators like
eqfor string equality. However, this doesn't save it from the non-transitivity of lossy casts:
"0 foo"is truthy in a boolean context, but is equal to
if ( ! $foo ) ..and
$false = (1 == 2); if ( $foo == $false ) ...don't give the same result. I guess the language is missing a "boolean equality" operator which could treat this consistently... Dec 19, 2016 at 13:20
Although "0" is 0 when evaluated as numeric, when we use a string in a boolean context (for example in an if statement), we are not interested in its numeric value. If we want to interpret it as numeric, we would compare it with some number, for example,
$_POST['id'] == 0, which makes the intent clear that we want to treat the user input as a number. Dec 20, 2016 at 1:20
1@MestreLion That example was of Perl rather than PHP. The crucial difference being that there is no separate boolean type in Perl, so
$falseends up set to
0; so when you write
$foo == $false, Perl doesn't know you want a boolean comparison, and casts to int instead. In PHP, that doesn't happen, because
$falseis boolean false, so
==casts to boolean, giving the same result as
!Sep 29, 2018 at 14:09
According to the PHP documentation on booleans, it says that:
When converting to boolean, the following values are considered
the empty string, and the string "0"
Every other value is considered TRUE (including any resource).
If you run:
It will print:
So it's working as expected.
To explicitly answer your question:
However, in most cases the cast is unnecessary, since a value will be automatically converted if an operator, function or control structure requires a boolean argument.
This means that PHP's "autocast" will cast "0" to integer 0, which is
FALSE as well in a control structure like say an
I would like to know the rationale of the design decision treating "0" as FALSE when converted to boolean, rather than the need of explicit casting. Dec 20, 2016 at 1:17
'0'is treated as
$x + 1, why shouldn't it also be treated as
0, and therefore
if ( $x )?