Comparisons between strings and numbers using == and other non-strict comparison operators currently work by casting the string to a number, and subsequently performing a comparison on integers or floats. This results in many surprising comparison results, the most notable of which is that 0 == "foobar" returns true. This RFC proposes to make non-strict comparisons more useful and less error prone, by using a number comparison only if the string is actually numeric. Otherwise the number is converted into a string, and a string comparison is performed.

PHP supports two different types of comparison operators: The strict comparisons === and !== , and the non-strict comparisons == , != , > , >= , < , <= and <=> . The primary difference between them is that strict comparisons require both operands to be of the same type, and do not perform implicit type coercions. However, there are some additional differences:

Strict comparison compares strings with strcmp() semantics, while non-strict comparison uses a “smart” comparison method that treats strings as numbers if they are numeric.

Strict comparison requires that arrays have keys occurring in the same order, while non-strict comparison allows out-of-order keys.

Strict comparison compares objects by object identity, while non-strict comparison compares their values.

The current dogma in the PHP world is that non-strict comparisons should always be avoided, because their conversion semantics are rarely desirable and can easily lead to bugs or even security issues. The single largest source of bugs is likely the fact that 0 == "foobar" returns true. Quite often this is encountered in cases where the comparison is implicit, such as in_array() or switch statements. A classic example:

This is an unfortunate state of affairs, because the concept of non-strict comparisons is not without value in a language like PHP, which commonly deals with mixtures of numbers in both plain and stringified form. Considering 42 and "42" as the same value is useful in many contexts, in part also due to the implicit conversions performed by PHP (e.g. string array keys may be converted to integers). Additionally some constructs (such as switch) only support non-strict comparison natively.

Unfortunately, while the idea of non-strict comparisons has some merit, their current semantics are blatantly wrong in some cases and thus greatly limit the overall usefulness of non-strict comparisons.

This RFC intends to give string to number comparisons a more reasonable behavior: When comparing to a numeric string, use a number comparison (same as now). Otherwise, convert the number to string and use a string comparison. The following table shows how the result of some simple comparisons changes (or doesn't change) under this RFC :

Comparison | Before | After ------------------------------ 0 == "0" | true | true 0 == "0.0" | true | true 0 == "foo" | true | false 0 == "" | true | false 42 == " 42" | true | true 42 == "42foo" | true | false

An alternative way to view these comparison semantics is that the number operand is cast to a string, and the strings are then compared using the non-strict “smart” string comparison algorithm. Compare the above table with the following results for string to string comparisons (which are not changed by this RFC ):

Comparison | Result ------------------------ "0" == "0" | true "0" == "0.0" | true "0" == "foo" | false "0" == "" | false "42" == " 42" | true "42" == "42foo" | false

This description of the comparison semantics is slightly simplified, and the detailed rules will be outlined in the following, but it should give an intuitive understanding of the new rules and provide a motivation for why they were chosen.