Проблема рекурсивной функции в PHP перезаписывает результат при переходе к новому дочернему элементу в ширину - PullRequest
1 голос
/ 31 января 2020

У меня есть структура базы данных:

+----+-----------+-----------+
| ID |   Name    | Parent_ID |
+----+-----------+-----------+
|  1 | 123a      | 2         |
|  2 | Microsoft | 3         |
|  3 | Apple     | 14        |
|  5 | IBM       | 14        |
| 14 | Amazon    | NULL      |
+----+-----------+-----------+

Я хочу получить массив всех дочерних элементов определенного идентификатора.

Так что, если я запускаю свою функцию с ID = 14, я хочу получить следующий результат:

array (size=2)
  0 => 
    array (size=3)
      'orgid' => string '3' (length=1)
      'name' => string 'Apple' (length=5)
      'parent_id' => string '14' (length=1)
  1 => 
    array (size=3)
      'orgid' => string '5' (length=1)
      'name' => string 'IBM' (length=3)
      'parent_id' => string '14' (length=2)

Это код, который у меня пока есть:

    function get_all_children_from_tree($orgparentid, $childrenArray = null)
    {
        $CI = get_instance();
        $CI->load->model('organization/organization_model');

        $allChildrenOrgs = $CI->organization_model->getAllChildrenForParent($orgparentid);
        if (empty($childrenArray)) {
            $childrenArray = [];
        }

        foreach ($allChildrenOrgs as $org)
        {
            $org_id = $org->org_id;
            $org_name = $org->name;
            $org_parent_id = $org->parent_id;
            $arr = array('orgid' => $org_id, 'name' => $org_name, 'parent_id' => $org_parent_id);
            array_push($childrenArray, $arr);

            if (!empty($org_id)) {
                get_all_children_from_tree($org_id, $childrenArray);
            }
        }
        return $childrenArray;
    }

Детализация глубины сначала для первого потомка прекрасно работает и дает мне правильный результат, но как только я введу второго потомка root (в нашем примере IBM), результирующий массив возвращается к своему первоначальному значению при точка, где вызывается рекурсивная функция. И таким образом все дети исключаются из результата.

Например, результат с моим кодом и данными примера, как указано выше, будет:

array (size=5)
  0 => 
    array (size=3)
      'orgid' => string '14' (length=1)
      'name' => string 'Amazon' (length=6)
      'parent_id' => NULL
  4 => 
    array (size=3)
      'orgid' => string '5' (length=1)
      'name' => string 'IBM' (length=3)
      'parent_id' => string '14' (length=2)

1 Ответ

3 голосов
/ 31 января 2020

Если вы используете MySQL 8+, вы можете полностью решить эту проблему в базе данных, используя рекурсивный иерархический CTE:

WITH RECURSIVE cte (id, name, parent_id) AS (
    SELECT ID, Name, Parent_ID
    FROM yourTable
    WHERE ID = 14
    UNION ALL
    SELECT t1.ID, t1.Name, t1.Parent_ID
    FROM yourTable t1
    INNER JOIN cte t2 ON t1.Parent_ID = t2.ID
)

SELECT * FROM cte;

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

...