0

我目前正在接触一些遗留代码以试图清理它并且遇到了一些难题。我解决它甚至不是远程任务关键,所以最多认为这是一个体育问题,但它仍然让我感到困惑。让我好奇。

这段代码:

// 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);
}

...同时抛出 12 个通知(“ Notice: Array to string conversion ...”),按预期$workTables工作,通过根据 对所有元素进行排序Update_time

('x' 列是我试图排除Name它与由.)work_table_1367940392work_table_1367940395NameUpdate_time

显然,由于我不想巧合地编程,至少这将被替换为:

// 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);
}

...符合 的描述array_multisort()做我们想要的,并且不会在我们的脸上扔通知。

但我真正感兴趣的是为什么旧代码有效(尽管有通知)。

部分原因似乎是asort()and co. 的行为,它们具有(部分)未记录的特性,即它们可以通过根据数组的内容进行操作,从“左到右”通过结构来处理多维数组(至少在PHP 5.4.7 (cli))......但是......我一直在努力理解正在发生的事情$workTables$sort可互换”。

我试图查看 PHP 的 C 源代码来弄清楚,但我一直试图理解这里发生的事情:

/* Do the actual sort magic - bada-bim, bada-boom. */
zend_qsort(indirect, array_size, sizeof(Bucket **), php_multisort_compare TSRMLS_CC);

...因为我对 C 的了解已经严重生锈,而且zend_qsort()它本身完全超出了我的范围。

有接盘侠吗?

请记住,我并不急于得到答案,所以不要花太多时间在这上面,但也许其他人也喜欢谜题?:)

就个人而言,我在这方面投入了一些时间,纯粹是因为我更喜欢彻底理解代码,尤其是当我试图清理它时——即使它只是巧合的代码。在进一步理解方面,我刚刚走到了死胡同,所以 stackoverflow 似乎是进一步启蒙的最佳机会。

所以,如果你对幕后发生的事情有一个想法(我怀疑这是我忽略的一些微不足道的事情;这往往是我兜了一圈圈后的问题),我很想听听!:)

4

1 回答 1

1

据我了解,正在创建一个数组并将其存储在$sort[$key]. 然后,一旦您调用array_multisort(),它碰巧将数组转换回字符串并使用该字符串作为定义顺序的值进行排序 - 正如警告所说。然后,将该字符串用作订单定义值。

这个转换数组->字符串是如何执行的?只是做echo $anArrayValueHere;是没有帮助的;它打印出来Array。类似的技巧,echo "" . $anArrayValueHere . "";也不会产生任何有用的东西。(但它也不会产生通知!)

很有可能serialize()被使用。假设,让我们看看什么会被用作订单定义值:

#!/usr/bin/php5
<?php
$sort[0]["Update_time"] = '2012-12-04 04:40';
echo serialize($sort[0]);

然后

$ ./php tmp.php
a:1:{s:11:"Update_time";s:16:"2012-12-04 04:40";}

看起来键将足够确定以产生可用于定义排序顺序的东西,就像Update_time值一样。

我不确定它serialize()是否被使用,但如果是,我认为这就是解释。

于 2013-05-07T15:59:23.037 回答