Родительское дочернее дерево с идентификаторами, распределенными по нескольким массивам / таблицам

Я унаследовал структуру таблицы, которую никогда не видел для родительского / дочернего дерева. Это не типичная проблема родительского / дочернего дерева в массиве.

Он включает в себя 3 массива; Компании, подразделения, пользователи

Несколько правил

  1. Всегда есть корневой узел, который является компанией
  2. Подразделение может быть подузлом компании или подразделения
  3. Компания может быть подузлом компании или подразделения
  4. Пользователи никогда не имеют никаких подузлов

Вещи, которые я пробовал

Я искал как сумасшедший, чтобы увидеть, должен ли кто-то еще делать что-то подобное и ничего не нашел. Я пошел по пути рекурсивной функции и эталонного метода, начиная с массива компании. Но как только мне нужно начать присоединять компании или подразделения в качестве детей, а затем проверять, есть ли в этом подразделении какие-либо дочерние компании или подразделения, я полностью теряюсь в том, как это сделать на любой глубине.

Конечный результат, который я ищу

Это структура массива. Посмотрите эту картинку для полной структуры.

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 ответа

Решение

Это решение, которое я придумал. Не самый элегантный, но работает. Спасибо 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
                                            )

                                    )

                            )

                    )

            )

Это то, что я имел в виду. Я бы изменил две вещи, но это только я.

Начните с клиентов, потому что их родители уже присутствуют, в подразделении или компаниях. Затем обработайте подразделения, потому что их родители также уже присутствуют в компаниях, и если нет, то это разделение может быть добавлено как родительское.

Обработка этого способа приведет к удалению большого количества поисков, которые вы делаете, вы можете просто проверить индексы массива, чтобы увидеть, присутствует ли родительский элемент.

Я не слишком люблю 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
Другие вопросы по тегам