While trying to simulate a bit of PHP behaviour I stumbled across this:
$a=array(0 => 1, 'test' => 2);
$b=array('test' => 3, 0 => 1);
var_dump($a==$b, $a>$b, $b>$a);
According to the output from var_dump $b is bigger than $a. In the PHP manual there is a Transcription of standard array comparison which states that the values of the arrays are compared one by one and if a key from the first array is missing in the second array, the arrays are uncomparable. So far so good. But if I try this (change in the first element of $a only):
$a=array(0 => 2, 'test' => 2);
$b=array('test' => 3, 0 => 1);
var_dump($a==$b, $a>$b, $b>$a);
All three comparison results are false. This looks like “uncomparable” to me (because the > result is the same as the < result, while the arrays are not ==either, which makes no sense) but this does not fit the transcription from the PHP manual. Both keys are present in both arrays and I would expect $a to be bigger this time because the content of key 0 is bigger in $a (2 vs. 1).
I’ve tried to dig into the PHP source code and found zend_hash_compare() in zend_hash.c, but the code there seems to work as the manual describes.
What’s going on here?
It would seem that the comparison loop is in the case of > done over the right hand array and in the case of < done over the left hand array, ie always over the supposedly “lesser” array. The order of the elements is significant as the foreach loop in the transcription code respects array order.
In other words;
$a>$b loops over b and finds ‘test’ first. ‘test’ is greater in $b so $b is greater and it returns false.
$b>$a loops over a and finds ‘0’ first. ‘0’ is greater in $a so $a is greater and it returns false.
This would actually make sense, the “greater” array is then allowed to contain elements that the “lesser” array doesn’t and still be greater as long as all common elements are greater.