복붙노트

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

PHP

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

나는 (플랫 데이터베이스 결과에서) 페이지 / 카테고리의 배열을 취하고 부모 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
        )
)

내가 보아 왔던 거의 모든 솔루션을 보았고 거의 모든 솔루션을 시도했다. 스택 오버플로에는 여기에 많은 것들이 있지만 페이지와 카테고리 모두에서 작동 할만큼 충분히 일반적인 것을 얻지는 않았다.

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

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);
}

해결법

  1. ==============================

    1.아주 단순하고 일반적인 트리 구조 :

    아주 단순하고 일반적인 트리 구조 :

    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);
    

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

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

  2. ==============================

    2.나는이 질문이 오래되었다는 것을 알고 있지만, 매우 많은 양의 데이터를 제외하고는 매우 비슷한 문제에 직면했다. 몇 가지 어려움을 겪은 후, 나는 참조를 사용하여 결과 집합의 한 번에 트리를 만들 수 있었다. 이 코드는 꽤 좋지는 않지만 작동하며 매우 빠르게 작동합니다. 그것은 비 재귀 적입니다 - 즉, 결과 집합을 한 번 통과 한 다음 끝에 하나의 array_filter가 있습니다.

    나는이 질문이 오래되었다는 것을 알고 있지만, 매우 많은 양의 데이터를 제외하고는 매우 비슷한 문제에 직면했다. 몇 가지 어려움을 겪은 후, 나는 참조를 사용하여 결과 집합의 한 번에 트리를 만들 수 있었다. 이 코드는 꽤 좋지는 않지만 작동하며 매우 빠르게 작동합니다. 그것은 비 재귀 적입니다 - 즉, 결과 집합을 한 번 통과 한 다음 끝에 하나의 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 |
    +------+-------------+
    

    마지막 print_r은 다음과 같은 출력을 생성합니다 :

    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
                                    (
                                    )
    
                            )
    
                    )
    
            )
    
    )
    

    정확히 내가 찾던 것이 맞습니다.

  3. ==============================

    3.PHP를 사용하여 mysql 결과를 배열로 가져온 다음이를 사용할 수 있습니다.

    PHP를 사용하여 mysql 결과를 배열로 가져온 다음이를 사용할 수 있습니다.

    $categoryArr = Array();
    while($categoryRow = mysql_fetch_array($category_query_result)){
        $categoryArr[] = array('parentid'=>$categoryRow['parent_id'],
                'id'=>$categoryRow['id']);
       }
    
  4. from https://stackoverflow.com/questions/8587341/recursive-function-to-generate-multidimensional-array-from-database-result by cc-by-sa and MIT license