development

데이터베이스 결과에서 다차원 배열을 생성하는 재귀 함수

big-blog 2020. 10. 20. 07:49
반응형

데이터베이스 결과에서 다차원 배열을 생성하는 재귀 함수


(플랫 데이터베이스 결과에서) 페이지 / 카테고리의 배열을 취하고 상위 ID를 기반으로 중첩 된 페이지 / 카테고리 항목의 배열을 생성하는 함수를 작성하려고합니다. 모든 수준의 중첩을 수행 할 수 있도록이 작업을 재귀 적으로 수행하고 싶습니다.

예 : 하나의 쿼리로 모든 페이지를 가져오고 있는데 이것이 데이터베이스 테이블의 모습입니다.

+-------+---------------+---------------------------+
|   id  |   parent_id   |           title           |
+-------+---------------+---------------------------+
|   1   |       0       |   Parent Page             |
|   2   |       1       |   Sub Page                |
|   3   |       2       |   Sub Sub Page            |
|   4   |       0       |   Another Parent Page     |
+-------+---------------+---------------------------+

그리고 이것은 내 뷰 파일에서 처리하기 위해 끝내고 싶은 배열입니다.

Array
(
    [0] => Array
        (
            [id] => 1
            [parent_id] => 0
            [title] => Parent Page
            [children] => Array
                        (
                            [0] => Array
                                (
                                    [id] => 2
                                    [parent_id] => 1
                                    [title] => Sub Page
                                    [children] => Array
                                                (
                                                    [0] => Array
                                                        (
                                                            [id] => 3
                                                            [parent_id] => 1
                                                            [title] => Sub Sub Page
                                                        )
                                                )
                                )
                        )
        )
    [1] => Array
        (
            [id] => 4
            [parent_id] => 0
            [title] => Another Parent Page
        )
)

나는 내가 만난 거의 모든 솔루션을 살펴보고 시도했습니다 (여기 Stack Overflow에 많은 솔루션이 있지만 페이지와 범주 모두에서 작동하는 일반적인 것을 얻지 못했습니다.

여기에 가장 가까운 것이 있지만 첫 번째 수준의 부모에게 자식을 할당하기 때문에 작동하지 않습니다.

function page_walk($array, $parent_id = FALSE)
{   
    $organized_pages = array();

    $children = array();

    foreach($array as $index => $page)
    {
        if ( $page['parent_id'] == 0) // No, just spit it out and you're done
        {
            $organized_pages[$index] = $page;
        }
        else // If it does, 
        {       
            $organized_pages[$parent_id]['children'][$page['id']] = $this->page_walk($page, $parent_id);
        }
    }

    return $organized_pages;
}

function page_list($array)
{       
    $fakepages = array();
    $fakepages[0] = array('id' => 1, 'parent_id' => 0, 'title' => 'Parent Page');
    $fakepages[1] = array('id' => 2, 'parent_id' => 1, 'title' => 'Sub Page');
    $fakepages[2] = array('id' => 3, 'parent_id' => 2, 'title' => 'Sub Sub Page');
    $fakepages[3] = array('id' => 4, 'parent_id' => 3, 'title' => 'Another Parent Page');

    $pages = $this->page_walk($fakepages, 0);

    print_r($pages);
}

매우 간단하고 일반적인 트리 구축 :

function buildTree(array $elements, $parentId = 0) {
    $branch = array();

    foreach ($elements as $element) {
        if ($element['parent_id'] == $parentId) {
            $children = buildTree($elements, $element['id']);
            if ($children) {
                $element['children'] = $children;
            }
            $branch[] = $element;
        }
    }

    return $branch;
}

$tree = buildTree($rows);

알고리즘은 매우 간단합니다.

  1. 모든 요소의 배열과 현재 부모의 ID를 가져옵니다 (초기에는 0/ nothing / null/ whatever).
  2. 모든 요소를 ​​반복합니다.
  3. 는 IF parent_id요소의 당신이 1에있어 현재의 부모 ID를 일치 요소는 부모의 자식입니다. 현재 자녀 목록에 넣으십시오 (여기 :) $branch.
  4. 3.에서 방금 식별 한 요소의 ID를 사용하여 함수를 재귀 적으로 호출합니다. 즉, 해당 요소의 모든 자식을 찾아 요소로 추가합니다 children.
  5. 찾은 아이들의 목록을 반환하십시오.

즉,이 함수를 한 번 실행하면 주어진 부모 ID의 자식 요소 목록이 반환됩니다. 로 호출 buildTree($myArray, 1)하면 부모 ID가 1 인 요소 목록이 반환됩니다. 처음에는이 함수가 부모 ID가 0 인 상태로 호출되므로 부모 ID가없는 요소 인 루트 노드가 반환됩니다. 이 함수는 자식의 자식을 찾기 위해 자신을 재귀 적으로 호출합니다.


나는이 질문이 오래되었다는 것을 알고 있지만 매우 많은 양의 데이터를 제외하고는 매우 유사한 문제에 직면했습니다. 약간의 어려움을 겪은 후, 참조를 사용하여 결과 집합의 한 단계에서 트리를 구축 할 수있었습니다. 이 코드는 예쁘지는 않지만 작동하며 매우 빠르게 작동합니다. 비재 귀적입니다. 즉, 결과 집합에 대한 패스가 하나만 array_filter있고 끝에 하나만 있습니다 .

$dbh = new PDO(CONNECT_STRING, USERNAME, PASSWORD);
$dbs = $dbh->query("SELECT n_id, n_parent_id from test_table order by n_parent_id, n_id");
$elems = array();

while(($row = $dbs->fetch(PDO::FETCH_ASSOC)) !== FALSE) {
    $row['children'] = array();
    $vn = "row" . $row['n_id'];
    ${$vn} = $row;
    if(!is_null($row['n_parent_id'])) {
        $vp = "parent" . $row['n_parent_id'];
        if(isset($data[$row['n_parent_id']])) {
            ${$vp} = $data[$row['n_parent_id']];
        }
        else {
            ${$vp} = array('n_id' => $row['n_parent_id'], 'n_parent_id' => null, 'children' => array());
            $data[$row['n_parent_id']] = &${$vp};
        }
        ${$vp}['children'][] = &${$vn};
        $data[$row['n_parent_id']] = ${$vp};
    }
    $data[$row['n_id']] = &${$vn};
}
$dbs->closeCursor();

$result = array_filter($data, function($elem) { return is_null($elem['n_parent_id']); });
print_r($result);

이 데이터에서 실행되는 경우 :

mysql> select * from test_table;
+------+-------------+
| n_id | n_parent_id |
+------+-------------+
|    1 |        NULL |
|    2 |        NULL |
|    3 |           1 |
|    4 |           1 |
|    5 |           2 |
|    6 |           2 |
|    7 |           5 |
|    8 |           5 |
+------+-------------+

The last print_r produces this output:

Array
(
    [1] => Array
        (
            [n_id] => 1
            [n_parent_id] => 
            [children] => Array
                (
                    [3] => Array
                        (
                            [n_id] => 3
                            [n_parent_id] => 1
                            [children] => Array
                                (
                                )

                        )

                    [4] => Array
                        (
                            [n_id] => 4
                            [n_parent_id] => 1
                            [children] => Array
                                (
                                )

                        )

                )

        )

    [2] => Array
        (
            [n_id] => 2
            [n_parent_id] => 
            [children] => Array
                (
                    [5] => Array
                        (
                            [n_id] => 5
                            [n_parent_id] => 2
                            [children] => Array
                                (
                                    [7] => Array
                                        (
                                            [n_id] => 7
                                            [n_parent_id] => 5
                                            [children] => Array
                                                (
                                                )

                                        )

                                    [8] => Array
                                        (
                                            [n_id] => 8
                                            [n_parent_id] => 5
                                            [children] => Array
                                                (
                                                )

                                        )

                                )

                        )

                    [6] => Array
                        (
                            [n_id] => 6
                            [n_parent_id] => 2
                            [children] => Array
                                (
                                )

                        )

                )

        )

)

Which is exactly what I was looking for.


It is possible to use php to get the mysql result into array and then use it.

$categoryArr = Array();
while($categoryRow = mysql_fetch_array($category_query_result)){
    $categoryArr[] = array('parentid'=>$categoryRow['parent_id'],
            'id'=>$categoryRow['id']);
   }

참고URL : https://stackoverflow.com/questions/8587341/recursive-function-to-generate-multidimensional-array-from-database-result

반응형