Php 从SQL查询结果生成父/子数组菜单结构

Php 从SQL查询结果生成父/子数组菜单结构,php,recursion,menu,parent-child,arrayofarrays,Php,Recursion,Menu,Parent Child,Arrayofarrays,我需要使用MySQL数据库查询来构建一个复杂的菜单结构。查询允许定义用户有权使用和查看的菜单项。菜单结构存储在经典的父/子关系中的结果集中,其中每个元素都有自己的id并依赖于其父id。父id=0表示该元素上方没有父元素(它是根): 如您所见,元素33和34位于元素32下,而元素32位于元素13下,最后元素13没有父元素,因为它是根元素(它的MNU_父元素为0)。 话虽如此,我已经开发了返回以下内容的代码: Array( [FLTMGR] => Array( [icon] =>

我需要使用MySQL数据库查询来构建一个复杂的菜单结构。查询允许定义用户有权使用和查看的菜单项。菜单结构存储在经典的父/子关系中的结果集中,其中每个元素都有自己的id并依赖于其父id。父id=0表示该元素上方没有父元素(它是根):

如您所见,元素33和34位于元素32下,而元素32位于元素13下,最后元素13没有父元素,因为它是根元素(它的MNU_父元素为0)。 话虽如此,我已经开发了返回以下内容的代码:

Array(
[FLTMGR] => Array(
    [icon] => fa fa-home
    [title] => STATO FLOTTA
    ),
[PSTN] => Array(
    [icon] => fa fa-map-marker
    [title] => POSIZIONI
    ),
[RTS] => Array(
    [icon] => fa fa-road
    [title] => PERCORSI
    ),
[CHRTS] => Array(
    [icon] => fa fa-line-charts
    [title] => DIAGRAMMI
    [sub] => Array(
            [SPD] => Array(
                [icon] => fa fa-tachometer
                [title] => VELOCITÁ
                ),
            [ALT] => Array(
                [icon] => fa fa-area-chart
                [title] => ALTITUDINE
                ),
            [DST] => Array(
                [icon] => fa fa-exchange
                [title] => DISTANZA
                ),
            [GSLN] => Array(
                [icon] => fa fa-tint blink
                [title] => CARBURANTE
                )
            )
        ),
...
[MNLS] => Array(
    [icon] => fa fa-book
    [title] => MANUALI
    [sub] => Array(
        [INSTL] => Array(
            [MNU_ID] => 32
            [MNU_FUNC] => INSTL
            [MNU_PARENT] => 13
            [icon] => fa fa-book
            [title] => INSTALLAZIONE
            [sub] => Array(
                [0] => Array(
                    [MNU_ID] => 33
                    [MNU_FUNC] => BASE
                    [MNU_PARENT] => 32
                    [icon] => fa fa-wrench
                    [title] => BASE
                    ),
                [1] => Array(
                    [MNU_ID] => 34
                    [MNU_FUNC] => FLPR
                    [MNU_PARENT] => 32
                    [icon] => fa fa-wrench
                    [title] => SONDA CARB.
                    )
                )
            )
        )
    ),
[RGLTNS] => Array( 
    [icon] => fa fa-bank
    [title] => NORMATIVE
    )
)
Array(
[FLTMGR] => Array(
    [icon] => fa fa-home
    [title] => STATO FLOTTA
    ),
[PSTN] => Array(
    [icon] => fa fa-map-marker
    [title] => POSIZIONI
[RTS] => Array(
    [icon] => fa fa-road
    [title] => PERCORSI
    ),
[CHRTS] => Array(
    [icon] => fa fa-line-charts
    [title] => DIAGRAMMI
    [sub] => Array(
            [SPD] => Array(
                [icon] => fa fa-tachometer
                [title] => VELOCITÁ
                ),
            [ALT] => Array(
                [icon] => fa fa-area-chart
                [title] => ALTITUDINE
                ),
            [DST] => Array(
                [icon] => fa fa-exchange
                [title] => DISTANZA
                ),
            [GSLN] => Array(
                [icon] => fa fa-tint blink
                [title] => CARBURANTE
                )
            )
        ),
...
[MNLS] => Array(
    [icon] => fa fa-book
    [title] => MANUALI
    [sub] => Array(
        [INSTL] => Array(
            [icon] => fa fa-book
            [title] => INSTALLAZIONE
            [sub] => Array(
                [BASE] => Array(
                    [icon] => fa fa-wrench
                    [title] => BASE
                    ),
                [FLPR] => Array( 
                    [icon] => fa fa-wrench
                    [title] => SONDA CARB.
                    )
                )
            )
        )
    ),
[RGLTNS] => Array(
    [icon] => fa fa-bank
    [title] => NORMATIVE
    )
)
但是,正如你所看到的,我无法在第一级生成正确的结构。换句话说,如果查看MNLS下的INSTL元素,则会出现以下错误:

  • 项目MNU\u ID、MNU\u FUNC、MNU\u父项不应存在(请参见其他)
  • “sub”下的项在1中具有相同的错误
  • “sub”项下的项目应通过BASE、FLPR标识,而不是0和1标识
  • 因此,预期结构应如下所示:

    Array(
    [FLTMGR] => Array(
        [icon] => fa fa-home
        [title] => STATO FLOTTA
        ),
    [PSTN] => Array(
        [icon] => fa fa-map-marker
        [title] => POSIZIONI
        ),
    [RTS] => Array(
        [icon] => fa fa-road
        [title] => PERCORSI
        ),
    [CHRTS] => Array(
        [icon] => fa fa-line-charts
        [title] => DIAGRAMMI
        [sub] => Array(
                [SPD] => Array(
                    [icon] => fa fa-tachometer
                    [title] => VELOCITÁ
                    ),
                [ALT] => Array(
                    [icon] => fa fa-area-chart
                    [title] => ALTITUDINE
                    ),
                [DST] => Array(
                    [icon] => fa fa-exchange
                    [title] => DISTANZA
                    ),
                [GSLN] => Array(
                    [icon] => fa fa-tint blink
                    [title] => CARBURANTE
                    )
                )
            ),
    ...
    [MNLS] => Array(
        [icon] => fa fa-book
        [title] => MANUALI
        [sub] => Array(
            [INSTL] => Array(
                [MNU_ID] => 32
                [MNU_FUNC] => INSTL
                [MNU_PARENT] => 13
                [icon] => fa fa-book
                [title] => INSTALLAZIONE
                [sub] => Array(
                    [0] => Array(
                        [MNU_ID] => 33
                        [MNU_FUNC] => BASE
                        [MNU_PARENT] => 32
                        [icon] => fa fa-wrench
                        [title] => BASE
                        ),
                    [1] => Array(
                        [MNU_ID] => 34
                        [MNU_FUNC] => FLPR
                        [MNU_PARENT] => 32
                        [icon] => fa fa-wrench
                        [title] => SONDA CARB.
                        )
                    )
                )
            )
        ),
    [RGLTNS] => Array( 
        [icon] => fa fa-bank
        [title] => NORMATIVE
        )
    )
    
    Array(
    [FLTMGR] => Array(
        [icon] => fa fa-home
        [title] => STATO FLOTTA
        ),
    [PSTN] => Array(
        [icon] => fa fa-map-marker
        [title] => POSIZIONI
    [RTS] => Array(
        [icon] => fa fa-road
        [title] => PERCORSI
        ),
    [CHRTS] => Array(
        [icon] => fa fa-line-charts
        [title] => DIAGRAMMI
        [sub] => Array(
                [SPD] => Array(
                    [icon] => fa fa-tachometer
                    [title] => VELOCITÁ
                    ),
                [ALT] => Array(
                    [icon] => fa fa-area-chart
                    [title] => ALTITUDINE
                    ),
                [DST] => Array(
                    [icon] => fa fa-exchange
                    [title] => DISTANZA
                    ),
                [GSLN] => Array(
                    [icon] => fa fa-tint blink
                    [title] => CARBURANTE
                    )
                )
            ),
    ...
    [MNLS] => Array(
        [icon] => fa fa-book
        [title] => MANUALI
        [sub] => Array(
            [INSTL] => Array(
                [icon] => fa fa-book
                [title] => INSTALLAZIONE
                [sub] => Array(
                    [BASE] => Array(
                        [icon] => fa fa-wrench
                        [title] => BASE
                        ),
                    [FLPR] => Array( 
                        [icon] => fa fa-wrench
                        [title] => SONDA CARB.
                        )
                    )
                )
            )
        ),
    [RGLTNS] => Array(
        [icon] => fa fa-bank
        [title] => NORMATIVE
        )
    )
    
    现在是代码:

    // $MenuDB contains the Menu structure returned by the DB
    
    // Build the basic structure
    $new = array();
    foreach ($MenuDB as $a){
        $new[$a['MNU_PARENT']][] = $a;
        }
    
    // Calls the recursive function CreateTree 
    $tree = createTree($new, $new[0]);  
    
    // Make final correction (remove unwanted items and replace index with keys)
    $b=replaceKeys($tree);
    
    print_r($b);
    exit();
    
    function replaceKeys(array $input) {    
        foreach($input as $key => &$val){                   // Scan the input array, each element will go in $val, the key will be $key
            $input[$val['MNU_FUNC']]=$input[$key];          // Replace index with key, the key is the value of the field MNU_FUNC
            if(is_numeric($key)) unset($input[$key]);       // Remove the item with numeric key (index) and leave the item with non-numeric index (key)
            unset($val['MNU_ID']);                          // Remove ID
            unset($val['MNU_PARENT']);                      // Remove Parent
            unset($val['MNU_FUNC']);                        // Remove Function
            if(isset($val['sub'])) {                        // avoid to work with undefined items
                if (is_array($val['sub'])) {                // check if there are childs inside the 'sub' item
                    $val['sub'] = replaceKeys($val['sub']); // if we have childs, do it again recursively
                    unset($val['url']);                     // remove url element if we have childs
                    unset($val['url_target']);              // remove url_target element if we have childs
                    }
                }
            }
        return $input;
        }
    
    function createTree(&$list, $parent){
        $tree = array();
        foreach ($parent as $k=>$l){
            if(isset($list[$l['MNU_ID']])){
                $l['sub'] = createTree($list, $list[$l['MNU_ID']]);
                }
            $tree[] = $l;
            } 
        return $tree;
        }
    
    尽管我努力了,我还是不知道错误在哪里。
    我的工作流程有什么变化吗?

    您只能使用一个递归函数:

    function makeTree($array, $parent) {
        $return = [];
        foreach ($array as $key => $value) {
            if ($value['MNU_PARENT'] == $parent) {
                $return[$value['MNU_FUNC']] = [
                    'icon' => 'fa fa-' . $value['MNU_ICON'],
                    'title' => $value['MNU_TITLE_IT'],
                ];
                $subs = false;
                foreach ($array as $search) {
                    if ($search['MNU_PARENT'] == $value['MNU_ID']) {
                        $subs = true;
                    }
                }
                if ($subs === true) {
                    $return[$value['MNU_FUNC']]['subs'] = makeTree($array, $value['MNU_ID']);
                }
            }
        }
        return $return;
    }
    
    $new = makeTree($arr, 0);
    

    此代码解决了以下问题:

    $new = array();
    foreach ($MenuDB as $a){
        $new[$a['MNU_PARENT']][] = $a;
        }
    
    $tree = createTree($new, $new[0]);  
    
    print_r($tree).PHP_EOL;
    
    exit();
    
    
    function createTree(&$list, $parent){
        $tree = array();
        foreach ($parent as $k=>$l){
            if(isset($list[$l['MNU_ID']])){                       // check if current element has childs 
                $l['sub'] = createTree($list, $list[$l['MNU_ID']]); // build child structure inside 'sub'
                unset($l['url']);                                    // remove the 'url' item for elements having childs
                unset($l['url_target']);                             // remove the 'url_target' item for elements having childs
                }
            unset($l['MNU_ID']);                                    // remove the 'MNU_ID' item not needed anymore
            unset($l['MNU_PARENT']);                                // remove the 'MNU_PARENT' item not needed anymore
            //$tree[] = $l;
            $tree[$l['MNU_FUNC']]=$l;                               // while $tree[] = $l; will transfer the elements array to $tree using index, this one will will transfer the elements array to $tree using the key $l['MNU_FUNC'] 
            unset($tree[$l['MNU_FUNC']]['MNU_FUNC']);               // remove the 'MNU_FUNC' item not needed anymore 
            } 
        return $tree;
        }
    

    这是更短甚至更粗的!,我们确实不需要两个段落,因此不再需要
    replaceKeys
    ,我们可以在
    createTree

    中完成所有内容,您可以使用ajax吗。。。?不幸的是,我不能使用Ajax调用,因为这段代码用于服务器端脚本来构建框架菜单。我唯一能做的就是MySQL查询和php脚本。你能显示你从Database获取的数据的var_dump吗?@J.Litvak$MenuDB包含数据库中的数据,就像你在我的帖子中看到的那样。你说得对+1您的代码工作完美,您的想法是正确的!我发现了这个问题:元素INSTL没有child,但是它的元素有child!!!这就是递归停止的原因。我也要发布我修改过的代码。。。