将PHP数组转换为ExtJS TreePanel格式

时间:2012-09-18 19:47:26

标签: php cakephp extjs

我的数据库吐出了这样的层次结构数组:

Array(
    [0] => array(
        [level] => 0
        [wo_number] => foo1
        [parent] => NULL
    )
    [1] => array(
        [level] => 1
        [wo_number] => foo2
        [parent] => foo1
    )
    [2] => array(
        [level] => 2
        [wo_number] => bar1
        [parent] => foo2
    )
    [3] => array(
        [level] => 2
        [wo_number] => bar2
        [parent] => foo2
    )
    [4] => array(
        [level] => 2
        [wo_number] => bar3
        [parent] => foo2
    )
    [5] => array(
        [level] => 2
        [wo_number] => bar4
        [parent] => foo2
    )
    [6] => array(
        [level] => 2
        [wo_number] => bar5
        [parent] => foo2
    )
)

每个数组节点都有一个引用数组中另一个节点的父键。

我需要将数组转换为这样的格式:

Array(
    [0] => array(
        [level] => 0
        [wo_number] => foo1
        [parent] => NULL
        [children] => array(
            [0] => array(
                [level] => 1
                [wo_number] => foo2
                [parent] => foo1
                [children] => array(
                    etc etc etc
                )
            )
        )
    )
)

这样我就可以对它进行json_encode,并在ExtJS TreePanel中使用它。

3 个答案:

答案 0 :(得分:1)

使用slighlty更改的功能(来自我在评论中链接的内容):

/**
 * Helper function
 * 
 * @param array  $d flat data, implementing a id/parent id (adjacency list) structure
 * @param mixed  $r root id, node to return
 * @param string $p parent id index
 * @param string $k id index
 * @param string $c children index
 * @return array
 */
function flat2nested($d, $r = 0, $p = 'parent', $k = 'id', $c = 'children') {
  $m = array();
  foreach ($d as $e) {
    isset($m[$e[$p]]) ?: $m[$e[$p]] = array();
    isset($m[$e[$k]]) ?: $m[$e[$k]] = array();
    $m[$e[$p]][] = array_merge($e, array($c => &$m[$e[$k]]));
  }

  return $m[$r]; // removed the `[0]` here
}

您可以轻松打电话,例如:

flat2nested($input, null, $p = 'parent', $k = 'wo_number');

虽然目前没有设置leaf索引,但由于这似乎总是false,因此在输入数组中设置它会更容易。

演示:http://codepad.viper-7.com/IKRLUO

如果您对flat2nested(或makeRecursive)的内部运作方式有疑问,请发表评论,我会延长答案。

答案 1 :(得分:0)

我修改了Yoshi指向我的makeRecursive()函数来执行以下操作:

    public function makeRecursive($d, $r = 0, $pk = 'parent', $k = 'wo_number', $c = 'children') {
            $m = array();
            foreach ($d as $e) {
                    isset($m[$e[$pk]]) ?: $m[$e[$pk]] = array();
                    isset($m[$e[$k ]]) ?: $m[$e[$k ]] = array();
                    $m[$e[$pk]][] = array_merge($e, array($c => &$m[$e[$k]]));
            }
            $final = array(
                    'wo_number'=>$r,
                    'leaf'=>false,
                    'children'=>$m[$r]
            );
            return $final;
    }

这解决了我的问题!

答案 2 :(得分:0)

我遇到同样的问题,并且在结构{DictDataArray: [{Id, parentId, Name}]}的商店扩展程序收到的数据之后,在javascript下解决了它非常简单

appendRawData: function(data){
            var me = this;
            var rNode = me.getRootNode();
            data = (Ext.isString(data) && Ext.decode(data)) || data;
            function ParentFilter(element, index, array){
                return element.ParentId == this.filterId;
            };

            function BuildTree(list, filter){
                var tmp = list.filter(ParentFilter, filter);
                if(tmp && tmp.length)
                {
                    var node= (filter.filterId && me.getById(filter.filterId)) || rNode;
                    node && node.appendChild && node.appendChild(tmp);
                }
                for(var item in tmp){
                    BuildTree(list, {filterId: tmp[item].Id});
                    var node= me.getById(tmp[item].Id);
                    node.set('leaf', !node.hasChildNodes());
                }
            };
            data && data.DictDataResult && BuildTree(data.DictDataResult, {filterId: null});
        },

并在加载简单调用后

store.appendRawData(response)

但其他方法是创建自己的读者并通过重载此函数将数据表示到loadData中,该函数读取原始数据并根据需要进行转换