I'm currently touching some legacy code in an attempt to clean it and have come across something of a puzzle. It's not even remotely mission critical that I resolve it, so consider this a sporting question at most, but it's still perplexing me. Colour me curious.
This code:
// dummy data for the sake of testing / abstract visualisation;
// x is thrown in as an experiment:
$workTables = array(
array('x' => 5, 'Name' => 'foo3', 'Update_time' => '2013-04-04 04:40',),
array('x' => 4, 'Name' => 'foo4', 'Update_time' => '2013-04-01 04:40',),
array('x' => 3, 'Name' => 'foo2', 'Update_time' => '2013-04-04 09:40',),
array('x' => 2, 'Name' => 'foo1', 'Update_time' => '2013-04-12 04:40',),
array('x' => 1, 'Name' => 'foo5', 'Update_time' => '2012-12-04 04:40',),
);
// original legacy code:
if (!empty($workTables)) {
$sort = array();
foreach ($workTables as $key => $value) {
$sort[$key]["Update_time"] = $value["Update_time"];
}
array_multisort($workTables, SORT_ASC, SORT_STRING, $sort);
}
...while throwing twelve notices ("Notice: Array to string conversion ...
"), works as expected, by ordering all elements in $workTables
according to Update_time
.
(The 'x' column is part of my attempt to rule out that it has anything to do with Name
, which in the original code is a fixed prefix followed by a timestamp (e.g. work_table_1367940392
, work_table_1367940395
, ...), making sorting by Name
equivalent to sorting by Update_time
.)
Obviously, since I don't want to program by coincidence, at the very least this is going to be replaced with:
// new code:
if (!empty($workTables)) {
$sort = array();
foreach ($workTables as $key => $value) {
$sort[$key] = $value["Update_time"];
}
array_multisort($sort, SORT_ASC, SORT_STRING, $workTables);
}
...which conforms to the description of array_multisort()
, also does what we want, and doesn't throw Notices in our face.
But what I'm really interested in is why the old code works (notices notwithstanding).
A partial reason seems to be the behaviour of asort()
and co., which have the (partly) undocumented feature that they can work with multi-dimensional arrays by acting according to the contents of the array, working through the structure from "left to right" (at least in PHP 5.4.7 (cli)
)... but... I'm stuck trying to comprehend what's making $workTables
and $sort
'interchangable'.
I've tried to look at PHP's C source code to figure it out, but I'm stuck at trying to understand what happens here:
/* Do the actual sort magic - bada-bim, bada-boom. */
zend_qsort(indirect, array_size, sizeof(Bucket **), php_multisort_compare TSRMLS_CC);
...since my knowledge of C has rusted terribly and zend_qsort()
itself is just flatly out of my league.
Any takers?
Keep in mind I'm not desperate for an answer, so don't sink too much time into this, but maybe someone else likes a puzzle, too? :)
Personally, I've invested some time into this purely because I prefer understanding code thoroughly, especially when I'm trying to clean it up - even if it's code that works only by coincidence. I've just reached a dead-end when it comes to further comprehension, so stackoverflow seemed like the best chance for further enlightenment.
So, if you have an idea about what's going on behind the scenes (I suspect it's something trivial I've overlooked; that tends to be my problem after going around in circles for a while), I'd love to hear it! :)