具有 ID 的父子树分布在多个 arrays/tables

Parent child tree with ID's spread through multiple arrays/tables

我继承了一个 table 结构,这是我从未见过的 parent/child 树。这不是典型的 parent/child 树到数组的问题。

涉及3个数组;公司、部门、用户

几条规则

  1. 总有一个根节点是公司
  2. 部门可以是公司或部门的子节点
  3. 公司可以是公司或部门的子节点
  4. 用户从来没有任何子节点

我试过的东西

我疯狂地搜索,看看是否有其他人不得不做类似的事情,但一无所获。我沿着递归函数和引用方法的道路前进,从公司数组开始。但是一旦我需要开始将公司或部门作为子部门附加,然后检查该部门是否有任何子公司或部门,我就完全迷失了如何使它更深入。

我正在寻找最终结果

这个数组结构。 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
            )
    )

这是我想到的解决方案。不是最优雅的,但它确实有效。感谢 RST 的帮助。

build_tree() 基本上是在函数的第一遍构建树。函数结束时,如果company/divisions/users数组中还有数据,则递归调用自身

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
                                            )

                                    )

                            )

                    )

            )

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

从客户开始,因为他们 parent 已经存在,无论是在部门还是在公司。然后处理部门,因为他们的 parent 也已经存在于公司中,如果没有,则可以将此部门添加为 parent.

以这种方式处理它会减少您正在进行的大量搜索,您可以只检查数组索引以查看是否存在 parent。

我不太喜欢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