Search code examples
phpphp-8

Why does PHP 8 treat 42 == " 42" as true?


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?


Solution

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

    <?php
    // the == operator does type juggling and also handles numerical strings differently:
    var_export("42" == "42"); // true
    var_export(42 == "42"); // true
    var_export("42" == " 42"); // true
    var_export("42" == "42 "); // false in PHP 7 and true in PHP 8
    var_export("42" == "042"); // true
    var_export("10" == "1e1"); // true
    var_export("abc" == " abc"); // false
    var_export("42" == "abc 42"); // false
    
    echo "\n";
    
    // the === operator does not do type juggling and does not handle numerical strings differently:
    var_export("42" === "42"); // true
    var_export(42 === "42"); // false
    var_export("42" === " 42"); // false
    var_export("42" === "42 "); // false
    var_export("42" === "042"); // false
    var_export("10" === "1e1"); // false
    var_export("abc" === " abc"); // false
    var_export("42" === "abc 42"); // false
    
    echo "\n";
    
    

    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:

    • The equality operator == behaves differently in PHP 8 than in PHP 7 for comparisons between numbers and non-numeric strings
    • What strings are considered numeric strings is different in PHP 8

    Regarding the latter point, read this:

    Numeric string handling has been altered [in PHP 8] to be more intuitive and less error-prone. Trailing whitespace is now allowed in numeric strings for consistency with how leading whitespace is treated. This mostly affects:

    • The is_numeric() function
    • String-to-string comparisons
    • Type declarations
    • Increment and decrement operations