在PHP中创建分层目录数组

时间:2010-08-21 23:27:06

标签: php mysql arrays kohana

我有以下代码(我知道此代码未经过优化,但不适合讨论):

function select_categories($cat_id)
{
    $this->db = ORM::factory('category')
            ->where('parent', '=', $cat_id)
            ->find_all();

    foreach ($this->db as $num => $category)
    {
        if($category->parent == 0)
        {
            $this->tmp[$category->parent][$category->id] = array();
        }
        else {
            $this->tmp[$category->parent][$category->id] = array();
        }

        $this->select_categories($category->id);
    }

    return $this->tmp;
}

函数返回此数组:

array(3) (
    0 => array(2) (
        1 => array(0) 
        2 => array(0) 
    )
    2 => array(1) (
        3 => array(0) 
    )
    3 => array(2) (
        4 => array(0) 
        5 => array(0) 
    )
)

但我应该如何更改代码

else {
    $this->tmp[$category->parent][$category->id] = array();
        // ^^^^^^^^^^^^^^^^^^^^^^ (this bit)
}

例如,要将array[3]合并到array[2][3](因为array[3]array[2]的子目录,而array[2]array[0][2]的子目录)所以,我需要这样做(当我不知道子目录的级别时):

array (
    0 => array (
        1 => array 
        2 => array (
                    3 => array (
                                4 => array
                                5 => array
                                ) 
                    ) 
    ) 
)

2 个答案:

答案 0 :(得分:2)

很久以前我在PHP中写了一些代码来做这件事。它需要一个实体列表(在您的情况下,类别)并返回一个结构,其中这些实体排列在树中。但是,它使用关联数组而不是对象;它假定“父”ID存储在其中一个关联数组条目中。我相信你可以根据自己的需要调整它。

function make_tree_structure ($nontree, $parent_field)
{
    $parent_to_children = array();
    $root_elements = array();

    foreach ($nontree as $id => $elem) {
        if (array_key_exists ($elem[$parent_field], $nontree))
            $parent_to_children [ $elem[$parent_field] ][] = $id;
        else
            $root_elements[] = $id;
    }

    $result = array();
    while (count ($root_elements)) {
        $id = array_shift ($root_elements);
        $result [ $id ] = make_tree_structure_recurse ($id, $parent_to_children, $nontree);
    }
    return $result;
}

function make_tree_structure_recurse ($id, &$parent_to_children, &$nontree)
{
    $ret = $nontree [ $id ];
    if (array_key_exists ($id, $parent_to_children)) {
        $list_of_children = $parent_to_children [ $id ];
        unset ($parent_to_children[$id]);
        while (count ($list_of_children)) {
            $child = array_shift ($list_of_children);
            $ret['children'][$child] = make_tree_structure_recurse ($child, $parent_to_children, $nontree);
        }
    }
    return $ret;
}

要了解这是做什么的,首先尝试在这样的结构上运行它:

var $data = array (
    0 => array('Name' => 'Kenny'),
    1 => array('Name' => 'Lilo', 'Parent' => 0),
    2 => array('Name' => 'Adrian', 'Parent' => 1)
    3 => array('Name' => 'Mark', 'Parent' => 1)
);

var $tree = make_tree_structure($data, 'Parent');

如果我没弄错的话,你应该得到这样的东西: (“父”键仍然存在,但为了清楚起见我将其留下了) < /子>

array (
    0 => array('Name' => 'Kenny', 'children' => array (
        1 => array('Name' => 'Lilo', 'children' => array (
            2 => array('Name' => 'Adrian')
            3 => array('Name' => 'Mark')
        )
    )
)

检查代码以了解它是如何做到这一点的。一旦了解了它的工作原理,就可以调整它以处理特定数据。

答案 1 :(得分:1)

假设您不希望阵列中包含任何数据/子标记:

foreach ($this->db as $num => $category)
{
    // save the data to the array
    $this->tmp[$category->id] = array();

    // save a reference to this item in the parent array
    $this->tmp[$category->parent][$category->id] = &$this->tmp[$category->id];

    $this->select_categories($category->id);
}

// the tree is at index $cat_id
return $this->tmp[$cat_id];

如果您只需要从数据库中检索完整的树,您甚至可以简化查询(一次获取所有记录)并删除此函数中的递归调用。如果不存在,您将需要额外的检查,只会设置$ this-&gt; tmp [$ catagory-&gt; id],否则它应该将数据与现有数据合并。