【问题标题】:Build a multidimensional array using recursive function使用递归函数构建多维数组
【发布时间】:2012-06-12 16:50:17
【问题描述】:

问题:

我正在尝试使用 MySQL 中的函数和数据构建递归树。但是,结果并不如预期。

PHP 代码:

function buildTree($root, $next = array()) 
{
    // Sanitize input
    $root = (int) $root;

    // Do query
    $query = "SELECT CID, Item, Parent FROM betyg_category WHERE Status = '1' AND Parent = '{$root}'";
    $result = mysql_query($query) or die ('Database Error (' . mysql_errno() . ') ' . mysql_error());

    // Loop results
    while ($row = mysql_fetch_assoc($result)) 
    {
      $next[$row['CID']] = array (
                                'CID' => $row['CID'], 
                                'Item' => $row['Item'], 
                                'Parent' => $row['Parent'], 
                                'Children' => buildTree($row['CID'], $next)
                            );
    }

    // Free mysql result resource
    mysql_free_result($result);

    // Return new array
    return $next;
}

$testTree = buildTree(0);

echo "<xmp>".print_r($testTree, true)."</xmp>";

数据库中的表如下所示:

我希望数组是这样的:

Array
(
    [1] => Array
    (
        [CID] => 1
        [Item] => Litteratur
        [Parent] => 0
        [Children] => Array
            (
                [2] => Integration av källorna
                [3] => Belysning av egna resultat
                [4] => Referenser
            )

    )

    and so forth..
)

也就是说,对于每个父母 => 生孩子,然后转到下一个父母等等。提前感谢您的任何建议。

【问题讨论】:

  • 你为什么不提供你得到的结果,这样人们就可以看到你当前从你的代码中产生了什么
  • @Lee 我想这样做,但结果会一直循环下去,我必须按转义键,这样浏览器才不会崩溃。换句话说,这个列表太长了,我觉得还不够。
  • 将 buildTree($row['CID'], $next) 更改为 buildTree($row['CID']) ... 现在会发生什么?
  • 如何添加一个计数器来记录已通过的行数,然后在该点之后返回,以进行调试。此外,您真的应该使用准备好的语句。我知道您可以通过将参数转换为整数来避免 SQL 注入,但这是事情的原理。另外,我假设 php 允许你使用任何数组索引,或者你的数组的顶层可能太稀疏(它太长了)。

标签: php mysql sql arrays recursion


【解决方案1】:

这里不需要递归。事实上,这将是非常低效的,因为您最终会遇到 SELECT N+1 问题。只需按父级排序结果集:

$query = "SELECT CID, Item, Parent FROM betyg_category WHERE Status = '1' ORDER BY Parent";
$result = mysql_query($query);

$tree = array();
while($row = mysql_fetch_assoc($result)) {
    if($row['Parent'] == 0) {
        $row['Children'] = array();
        $tree[$row['CID']] = $row;
    } else {
        $tree[$row['Parent']]['Children'][] = $row;
    }
}

这将产生以下内容:

Array
(
    [1] => Array
        (
            [CID] => 1
            [Item] => Litteratur
            [Parent] => 0
            [Children] => Array
                (
                    [0] => Array
                        (
                            [CID] => 2
                            [Item] => Integration av källorna
                            [Parent] => 1
                        )

                    [1] => Array
                        (
                            [CID] => 3
                            [Item] => Belysning
                            [Parent] => 1
                        )

                    [2] => Array
                        (
                            [CID] => 4
                            [Item] => Referenser
                            [Parent] => 1
                        )

                )

        )

    [5] => Array
        (
            [CID] => 5
            [Item] => Validitet
            [Parent] => 0
            [Children] => Array
                (
                    [0] => Array
                        (
                            [CID] => 6
                            [Item] => Huvudsyfte
                            [Parent] => 5
                        )

                )

        )

)

如果你只想要每个孩子的名字,改变,使用$tree[$row['Parent']]['Children'][] = $row['Item'];反而。

【讨论】:

  • 这很好用,只是我不得不将其更改为: $tree[$row['Parent']]['Children'][$row['CID']] = $row['物品']; - 但问题仍然存在。如何对数组索引以及更重要的是子项的索引进行排序?
  • @kexxcream 你想怎么排序?
  • 我希望它按索引键排序,但@sephoy08 提供了该问题的答案。
【解决方案2】:

试试这个:

$array = array();
while ($row = mysql_fetch_assoc($result)) 
{
    if($row['parent'] == '0')
    {
        $array[$row['parent']] = '';
        $array[$row['parent']]['CID'] = $row['CID'];
        $array[$row['parent']]['Item'] = $row['item'];
        $array[$row['parent']]['Parent'] = $row['parent'];
        $array[$row['parent']]['Children'] = '';

    }
    else
    {
        $array[$row['parent']]['Children'][$row['CID']] = $row['item'];
    }
}
echo "<pre>";
print_r($array);

首先在您的查询中。加ORDER BY CID ASC 那么

$count = array_keys($array);
foreach($count as $arr)
{
    ksort($array[$arr]['Children']);
}

【讨论】:

  • 谢谢,感谢@alexn 代码,我也设法找到了这个解决方案。但现在我只缺少一种按索引对 $array 和 Children 进行排序的方法。
  • 很好,这很好用。我已经在下面发布了最终解决方案。
【解决方案3】:

所有 cmets 的最终解决方案:

$query = "SELECT * FROM betyg_category WHERE Status = '1' ORDER BY CID ASC";
$result = mysql_query($query) or die ('Database Error (' . mysql_errno() . ') ' . mysql_error());

$tree = array();

while($row = mysql_fetch_assoc($result)) 
{
    if($row['Parent'] == 0) 
    {
        $row['Children'] = array();
        $tree[$row['CID']] = array(
                                'CID' => $row['CID'], 
                                'Item' => $row['Item'], 
                                'Parent' => $row['Parent']
                            );
    } 
    else 
    {
        $tree[$row['Parent']]['Children'][$row['CID']] = $row['Item'];
    }
}

$count = array_keys($tree);

foreach ($count as $array)
{
    ksort($tree[$array]['Children']);
}

echo "<xmp>".print_r($tree, true)."</xmp>";

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-15
    • 1970-01-01
    • 2011-11-13
    • 1970-01-01
    • 2017-12-28
    • 2017-11-28
    • 1970-01-01
    相关资源
    最近更新 更多