PHP 8 has been released. It has made changes to the behaviour of the equality operator. According to the documentation, this is how it behaves now:
Non-strict comparisons between numbers and non-numeric strings now work by casting the number to string and comparing the strings.
However, this expression evaluates to true both in PHP 8 and in earlier versions of PHP:
42 == " 42" // true
This doesn’t make sense to me. According to the documentation, the number should be cast to a string, "42"
, which surely is not equal to the string " 42"
, right?
2
Answers
Short answer:
In PHP 8 and in PHP 7,
42 == " 42"
is true, and in both PHP 7 and PHP 8,"42" == " 42"
is true.Long answer:
I think you have a misconception of how the equality operator
==
works in PHP. Both in PHP 8 and in earlier versions of PHP, the equality operator treats strings that look numeric differently from other strings:Even in PHP 8, the
==
operator both does type juggling and it handles numeric strings differently. That principle hasn't changed. What has changed in PHP 8 is:==
behaves differently in PHP 8 than in PHP 7 for comparisons between numbers and non-numeric stringsRegarding the latter point, read this:
The documentation you quote is actually correct, but could possibly be made clearer:
I’ve bolded the key phrase, which is "non-numeric strings".
Within various parts of PHP, there is the concept of a "numeric string" as a kind of pseudo-type: any string that looks like a number may be treated as one by parts of the language. This is to aid in PHP’s primary use case of taking data from a web request (which will always be strings) and using it in operations (which might want to treat it as numbers).
One of the places this comes into play is the
==
operator, which tries to be "smart" about what you’re trying to compare.If PHP decides that both sides of the
==
operator are either numbers or numeric strings, it will perform the comparison by casting them both to integer (or float, if appropriate) and seeing if they have the same numeric value. The definition of a "numeric string" is quite broad, and allows leading spaces; as of PHP 8, it now also allows trailing spaces, for consistency.So in your example,
" 42"
is a "numeric string",42
is an actual number, so the comparison performed is(int)" 42" === 42
The change described in your quote is for the case where one side is an actual number (an integer or float) and the other side is a non-numeric string, that is one which PHP has decided "doesn’t look like a number". In older versions of PHP, this would also cast to int, so
"hello" == 0
would evaluate(int)"hello" === 0
, which istrue
. In PHP 8, this case casts to string instead, so"hello" == 0
would evaluate"hello" === (string)0
, which isfalse
.