ID通过多个数组/表传播的父子树

时间:2015-03-07 09:25:32

标签: php arrays recursion parent-child

我继承了一个我从未见过父/子树的表结构。这不是阵列问题的典型父/子树。

它涉及3个阵列;公司,部门,用户

少数规则

  1. 总有一个根节点是公司
  2. 分部可以是公司或部门的子节点
  3. 公司可以是公司或部门的子节点
  4. 用户永远不会有任何子节点
  5. 我尝试过的事情

    我疯狂地搜索,看看是否有其他人不得不做类似的事情并且什么都没发现。我从公司数组开始,走了一个递归函数和引用方法的道路。但是,一旦我需要开始将公司或部门作为孩子加入,然后检查该部门是否有任何子公司或部门,我就完全迷失了如何使其进入任何深度。

    最终结果我正在寻找

    这个数组结构。的 Look a this picture for the full structure.

    Array
    (
        [company_799] => Array
                (
                    [companyid] => 799
                    [parent_companyid] => 0
                    [parent_divisionid] => 0
                    [companyname] => Main Company
                    [children] => Array
                        (
                            [user_3138] => Array
                                (
                                    [userid] => 3138
                                    [companyid] => 799
                                    [company_divisionid] => 
                                    [username] => test user 1
                                )
                            [division_58] => Array
                                (
                                     [divisionid] => 58
                                     [parent_companyid] => 799
                                     [parent_divisionid] => 0
                                     [division_name] => Division 1
                                     [children] => Array
                                         (
                                             [user_3139] => Array
    
           .. etc...
    

    公司数组

        Array
        (
            [799] => Array
                (
                    [companyid] => 799
                    [parent_companyid] => 0
                    [parent_divisionid] => 0
                    [companyname] => Main Company
                )
    
            [800] => Array
                (
                    [companyid] => 800
                    [parent_companyid] => 799
                    [parent_divisionid] => 0
                    [companyname] => Sub Company 1
                )
    
            [801] => Array
                (
                    [companyid] => 801
                    [parent_companyid] => 800
                    [parent_divisionid] => 0
                    [companyname] => Sub Company 2
                )
    
            [802] => Array
                (
                    [companyid] => 802
                    [parent_companyid] => 0
                    [parent_divisionid] => 59
                    [companyname] => Sub Company of Division
                )
        )
    

        Array
        (
            [58] => Array
                (
                    [divisionid] => 58
                    [parent_companyid] => 799
                    [parent_divisionid] => 0
                    [division_name] => Division 1
                )
    
            [60] => Array
                (
                    [divisionid] => 60
                    [parent_companyid] => 801
                    [parent_divisionid] => 0
                    [division_name] => Sub Division of Company
                )
    
            [59] => Array
                (
                    [divisionid] => 59
                    [parent_companyid] => 0
                    [parent_divisionid] => 58
                    [division_name] => Sub Division of division
                )
        )
    

    用户

        Array
        (
            [3138] => Array
                (
                    [userid] => 3138
                    [companyid] => 799
                    [parent_divisionid] => 0
                    [username] => test user 1
                )
    
            [3139] => Array
                (
                    [userid] => 3139
                    [companyid] => 799
                    [parent_divisionid] => 58
                    [username] => test user 2
                )
    
            [3140] => Array
                (
                    [userid] => 3140
                    [companyid] => 799
                    [parent_divisionid] => 59
                    [username] => test user 3
                )
    
            [3141] => Array
                (
                    [userid] => 3141
                    [companyid] => 802
                    [parent_divisionid] => 0
                    [username] => test user 4
                )
    
            [3142] => Array
                (
                    [userid] => 3142
                    [companyid] => 800
                    [parent_divisionid] => 0
                    [username] => test user 5
                )
        )
    

2 个答案:

答案 0 :(得分:1)

这是我提出的解决方案。不是最优雅,但它的工作原理。谢谢RST的帮助。

build_tree()在函数的第一次传递中基本构建了树。在函数结束时,如果公司/部门/用户数组中仍有数据,它将以递归方式调用自身。

public function get_tree()
{
    $arr_treedata              = array();
    $arr_treedata['tree']      = array(); // Where the final tree will be stored
    $arr_treedata['companies'] = $this->get_companies(); // From mysql table
    $arr_treedata['divisions'] = $this->get_divisions(); // From mysql table
    $arr_treedata['users']     = $this->get_users(); // From mysql table

    return $this->build_tree($arr_treedata);
}

private function build_tree($arr_treedata)
{
    // Append company nodes
    if (count($arr_treedata['companies']) > 0)
    {
        foreach ($arr_treedata['companies'] as $str_companyid => $arr_company)
        {
            $str_search_key = FALSE;
            if ($arr_company['parent_companyid'] == 0 && $arr_company['parent_divisionid'] == 0)
            {
                // Root node found
                $arr_treedata['tree'][$str_companyid] = $arr_company;
                unset($arr_treedata['companies'][$str_companyid]);
            }
            else if ($arr_company['parent_companyid'] > 0 && $arr_company['parent_divisionid'] == 0)
            {
                // Company is a child of a company
                $str_search_key = 'company_'.$arr_company['parent_companyid'];
            }
            else if ($arr_company['parent_companyid'] == 0 && $arr_company['parent_divisionid'] > 0)
            {
                // Company is a child of a division
                $str_search_key = 'division_'.$arr_company['parent_divisionid'];
            }

            if ($str_search_key !== FALSE)
            {
                // Search for the key
                $arr_insertdata = array('children' => array($str_companyid => $arr_company));
                $arr_newtreedata = $this->search_tree_and_insert($arr_treedata['tree'], $str_search_key, $arr_insertdata);
                if ($arr_treedata['tree'] != $arr_newtreedata)
                {
                    // Key found and new tree data detected
                    $arr_treedata['tree'] = $arr_newtreedata;
                    unset($arr_treedata['companies'][$str_companyid]);
                }
            }
        }
    }

    // Append division nodes
    if (count($arr_treedata['divisions']) > 0)
    {
        foreach ($arr_treedata['divisions'] as $str_divisionid => $arr_division)
        {
            $str_search_key = FALSE;
            if ($arr_division['parent_companyid'] != '' && $arr_division['parent_divisionid'] == '')
            {
                // Division is a child of a company
                $str_search_key = 'company_'.$arr_division['parent_companyid'];
            }
            else if ($arr_division['parent_companyid'] != '' && $arr_division['parent_divisionid'] != '')
            {
                // Division if a child of a division
                $str_search_key = 'division_'.$arr_division['parent_divisionid'];
            }

            if ($str_search_key !== FALSE)
            {
                // Search for the key
                $arr_insertdata = array('children' => array($str_divisionid => $arr_division));
                $arr_newtreedata = $this->search_tree_and_insert($arr_treedata['tree'], $str_search_key, $arr_insertdata);
                if ($arr_treedata['tree'] != $arr_newtreedata)
                {
                    // Key found and new tree data detected
                    $arr_treedata['tree'] = $arr_newtreedata;
                    unset($arr_treedata['divisions'][$str_divisionid]);
                }
            }
        }
    }

    // Append user nodes
    if (count($arr_treedata['users']) > 0)
    {
        foreach ($arr_treedata['users'] as $str_userid => $arr_user)
        {
            $str_search_key = FALSE;
            if ($arr_user['parent_companyid'] != '' && $arr_user['parent_divisionid'] == '')
            {
                // User is a child of a company
                $str_search_key = 'company_'.$arr_user['parent_companyid'];
            }
            else if ($arr_user['parent_companyid'] != '' && $arr_user['parent_divisionid'] != '')
            {
                // User if a child of a division
                $str_search_key = 'division_'.$arr_user['parent_divisionid'];
            }

            if ($str_search_key !== FALSE)
            {
                // Search for the key
                $arr_insertdata = array('children' => array($str_userid => $arr_user));
                $arr_newtreedata = $this->search_tree_and_insert($arr_treedata['tree'], $str_search_key, $arr_insertdata);
                if ($arr_treedata['tree'] != $arr_newtreedata)
                {
                    // Key found and new tree data detected
                    $arr_treedata['tree'] = $arr_newtreedata;
                    unset($arr_treedata['users'][$str_userid]);
                }
            }
        }
    }

    if (count($arr_treedata['divisions']) > 0 || count($arr_treedata['companies']) > 0 || count($arr_treedata['users']) > 0)
    {
        $arr_treedata = $this->build_tree($arr_treedata);
    }

    return $arr_treedata;
}

// Search the tree for an array key and merge the data
private function search_tree_and_insert($arr_treedata, $str_search_key, $arr_insertdata)
{
    foreach ($arr_treedata as $str_keyid => $arr_row)
    {
        if ($str_keyid == $str_search_key)
        {
            // Found key, merge in the provided data
            $arr_treedata[$str_keyid] = array_merge_recursive($arr_treedata[$str_keyid], $arr_insertdata);
        }
        else if (isset($arr_row['children']))
        {
            // Search Children
            $arr_treedata[$str_keyid]['children'] = $this->search_tree_and_insert($arr_row['children'], $str_search_key, $arr_insertdata);
        }
    }

    return $arr_treedata;
}

<强>结果

        [company_799] => Array
            (
                [companyid] => 799
                [parent_companyid] => 0
                [parent_divisionid] => 0
                [companyname] => Main Company
                [children] => Array
                    (
                        [company_800] => Array
                            (
                                [companyid] => 800
                                [parent_companyid] => 799
                                [parent_divisionid] => 0
                                [companyname] => Sub Company 1
                                [children] => Array
                                    (
                                        [company_801] => Array
                                            (
                                                [companyid] => 801
                                                [parent_companyid] => 800
                                                [parent_divisionid] => 0
                                                [companyname] => Sub Company 2
                                                [children] => Array
                                                    (
                                                        [division_60] => Array
                                                            (
                                                                [divisionid] => 60
                                                                [parent_companyid] => 801
                                                                [parent_divisionid] => 
                                                                [division_name] => Sub Division of Company
                                                            )

                                                    )

                                            )

                                    )

                            )

                        [division_58] => Array
                            (
                                [divisionid] => 58
                                [parent_companyid] => 799
                                [parent_divisionid] => 
                                [division_name] => Division 1
                                [children] => Array
                                    (
                                        [division_59] => Array
                                            (
                                                [divisionid] => 59
                                                [parent_companyid] => 799
                                                [parent_divisionid] => 58
                                                [division_name] => Sub Division of division
                                                [children] => Array
                                                    (
                                                        [user_3140] => Array
                                                            (
                                                                [userid] => 3140
                                                                [parent_companyid] => 799
                                                                [parent_divisionid] => 59
                                                                [username] => test user 3
                                                            )

                                                        [company_802] => Array
                                                            (
                                                                [companyid] => 802
                                                                [parent_companyid] => 0
                                                                [parent_divisionid] => 59
                                                                [companyname] => Sub Company of Division
                                                            )

                                                    )

                                            )

                                        [user_3139] => Array
                                            (
                                                [userid] => 3139
                                                [parent_companyid] => 799
                                                [parent_divisionid] => 58
                                                [username] => test user 2
                                            )

                                    )

                            )

                    )

            )

答案 1 :(得分:1)

这就是我的意思。我会改变两件事,但那只是我。

从客户开始,因为他们的父母已经在分部或公司中。然后处理分歧,因为他们的父母也已经出现在公司中,如果没有,那么这个部门可以作为父母加入。

以这种方式处理它会删除你正在进行的大量搜索,你可以检查数组索引以查看父项是否存在。

我不太喜欢if, elseif, elseif结构。我会把它改成

if ( ! empty($arr_company['parent_companyid'] ) {
   // add to company 
   // other actions 
   continue;
}

if ( ! empty($arr_company['parent_divisionid'] ) {
   // add to division 
   //other actions
  continue;
}  

// no company or division parent id    
// add to tree as new division/company