skip to Main Content

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


  1. Chosen as BEST ANSWER

    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

  2. The documentation you quote is actually correct, but could possibly be made clearer:

    Non-strict comparisons between numbers and non-numeric strings now work by casting the number to string and comparing the strings.

    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 is true. In PHP 8, this case casts to string instead, so "hello" == 0 would evaluate "hello" === (string)0, which is false.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search