0

There are some SO questions on this subject, but none of them answer it with an algorithm description, as it exists in JS (ECMAScript). It doesn't seems to exist in the PHP documentation.

I'm not a C developer and I could not even find the corresponding code in PHP sources. I will not sleep well anymore if I can't tell why (loose, ==) comparing a string/number/resource to an object/array seems to always return false?

Eg. why '' == [] is false, or why 'foo' == ['foo'] is false.

cdoublev
  • 709
  • 6
  • 18
  • 1
    i don't know what your actually asking but: http://php.net/manual/en/types.comparisons.php –  Dec 25 '17 at 14:58
  • Thank you but it doesn't tell a clue for why `'' == []` is `false`, or even why `'foo' == ['foo']` is `false` if we were presuming that an array coercion was happening. – cdoublev Dec 25 '17 at 16:16
  • Why was that question downvoted? This is a fundamental question about PHP understanding and there is no other question that got valuable answer. – Eric MORAND Jan 11 '18 at 11:01

2 Answers2

3

There are multiple pages in the PHP documentation dedicated to loose comparison with the == operator. For objects, see Comparing Objects:

When using the comparison operator (==), object variables are compared in a simple manner, namely: Two object instances are equal if they have the same attributes and values (values are compared with ==), and are instances of the same class.

For loose comparison between other types, see PHP type comparison tables.

MatsLindh
  • 49,529
  • 4
  • 53
  • 84
  • Thank you but it doesn't tell a clue for why `'' == []` is `false`, or even why `'foo' == ['foo']` is `false` if we were presuming that an array coercion was happening. – cdoublev Dec 25 '17 at 16:16
  • Because one is an array and the other is a string. There is no other explanation for _why_. There is no coercion to array in PHP, so I don't know why we should presume that any array coercion were happening (there is, however, explicit casting to string (either by your code or by code that expects a string), which will give you the string "Array" and a stern notice), so the fact that it is false is shown in the second table I linked (`array()` vs `"PHP"`). – MatsLindh Dec 25 '17 at 18:40
  • This is an opinion (thank you for providing it anyway), not the answer I was expecting, like a link to the PHP source code in charge of the rule you are describing to me, which I agree with of course, or some part of the documentation mentioning it. – cdoublev Dec 28 '17 at 23:57
  • @cdoublev An array is not a string, this is not an opinion. – EricLavault Dec 29 '17 at 09:01
  • People making Javascript (TC39) have not the same "opinion" for `'' == []`. I think that when two languages doesn't have the same opinion, we can say that they establish different rules, written in specifications (like ECMAScript for JS) and in source code. I can't find the specification or the source code part for this rule in PHP. – cdoublev Dec 29 '17 at 16:09
  • Have you read through the actual [langspec](https://github.com/php/php-langspec/blob/master/spec/10-expressions.md#relational-operators)? The comparison table given under relation operators might be what you want. The actual implementation is in [zend_operators.c](https://github.com/php/php-src/blob/b2b2b437af5495dcb2016be6e45567ed826cb87e/Zend/zend_operators.c#L1932). Neither of these explain _why_ something is as it is, just that it is. – MatsLindh Dec 29 '17 at 16:46
  • Sorry, I just saw your comment now. It surprise me that an official documentation affirms that with an equality comparison "Two objects of different types are always not equal." although it's plainly wrong. – cdoublev Dec 31 '17 at 17:38
  • Feel free to elaborate on situations where that isn't true ("When comparing two objects, if any of the object types has its own compare semantics, that would define the result, with the left operand taking precedence. Otherwise, if the objects are of different types, the comparison result is `FALSE`. If the objects are of the same type, the properties of the objects are compares using the array comparison described above."). Also be aware that there hasn't been a formal spec for PHP - the spec has been written after the fact to reflect the behaviour of PHP, not the other way around. – MatsLindh Dec 31 '17 at 20:14
2

I finally found an almost satisfying answer from this blog of a security expert (Gynvael) and by reading source code. From the former, I'm only quoting the parts that answer my initial question: why (loose, ==) comparing a string/number/resource to an object/array seems to always return false? The algorithm in charge of equivalent comparison (==) can be found here.

The main mechanics of the equality operator are implemented in the compare_function in php-src/Zend/zend_operators.c, however many cases call other functions or use big macros (which then call other functions that use even more macros), so reading this isn't too pleasant.

The operator basically works in two steps:

  1. If both operands are of a type that the compare_function knows how to compare they are compared. This behavior includes the following pairs of types (please note the equality operator is symmetrical so comparison of A vs B is the same as B vs A): • LONG vs LONG • LONG vs DOUBLE (+ symmetrical) • DOUBLE vs DOUBLE • ARRAY vs ARRAY • NULL vs NULL • NULL vs BOOL (+ symmetrical) • NULL vs OBJECT (+ symmetrical) • BOOL vs BOOL • STRING vs STRING • and OBJECT vs OBJECT

  2. In case the pair of types is not on the above list the compare_function tries to cast the operands to either the type of the second operand (in case of OBJECTs with cast_object handler), cast to BOOL (in case the second type is either NULL or BOOL), or cast to either LONG or DOUBLE in most other cases. After the cast the compare_function is rerun.

I think that all other cases return false.

cdoublev
  • 709
  • 6
  • 18