根据 SQL 查询结果构建 parent/child 数组菜单结构
Building a parent/child array menu structure from SQL query result
我需要使用 MySQL 数据库查询以动态方式构建复杂的菜单结构。该查询允许定义用户有权使用和查看的菜单项。 Menu 结构以经典的 parent/child 关系存储到结果集中,其中每个元素都有自己的 ID 并依赖于其父 ID。 Parent id = 0 表示该元素之上没有父元素(它是根):
MNU_ID MNU_FUNC MNU_PARENT MNU_ICON MNU_TITLE_IT MNU_TITLE_EN
----------------------------------------------------------------------------
1 FLTMGR 0 home STATO FLOTTA FLEET STATUS
2 PSTN 0 map-marker POSIZIONI POSITIONS
3 RTS 0 road PERCORSI ROUTES
4 CHRTS 0 line-charts DIAGRAMMI CHARTS
...
13 MNLS 0 book MANUALI MANUALS
14 RGLTNS 0 bank NORMATIVE REGULATIONS
16 SPD 4 tachometer VELOCITA' SPEED
17 ALT 4 area-chart ALTITUDINE ALTITUDE
18 DST 4 exchange DISTANZA DISTANCE
...
32 INSTL 13 book INSTALLAZIONE SETUP
33 BASE 32 wrench BASE BASE
34 FLPR 32 wrench SONDA CARB. FUAL PROBE
所以你可以看到元素 33 和 34 在元素 32 下面,而元素 32 在元素 13 下面,最后元素 13 没有父元素,因为它是根元素(它的 MNU_PARENT 是 0) .
好吧,我已经将我的代码开发为 return 以下内容:
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
)
)
但是如您所见,我无法在第一层生成正确的结构。换句话说,如果您查看 MNLS 下的 INSTL 元素,则会出现以下错误:
- 项目 MNU_ID、MNU_FUNC、MNU_PARENT 不应该存在(请参阅其他项目)
- '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(
[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
.
中完成所有内容
我需要使用 MySQL 数据库查询以动态方式构建复杂的菜单结构。该查询允许定义用户有权使用和查看的菜单项。 Menu 结构以经典的 parent/child 关系存储到结果集中,其中每个元素都有自己的 ID 并依赖于其父 ID。 Parent id = 0 表示该元素之上没有父元素(它是根):
MNU_ID MNU_FUNC MNU_PARENT MNU_ICON MNU_TITLE_IT MNU_TITLE_EN
----------------------------------------------------------------------------
1 FLTMGR 0 home STATO FLOTTA FLEET STATUS
2 PSTN 0 map-marker POSIZIONI POSITIONS
3 RTS 0 road PERCORSI ROUTES
4 CHRTS 0 line-charts DIAGRAMMI CHARTS
...
13 MNLS 0 book MANUALI MANUALS
14 RGLTNS 0 bank NORMATIVE REGULATIONS
16 SPD 4 tachometer VELOCITA' SPEED
17 ALT 4 area-chart ALTITUDINE ALTITUDE
18 DST 4 exchange DISTANZA DISTANCE
...
32 INSTL 13 book INSTALLAZIONE SETUP
33 BASE 32 wrench BASE BASE
34 FLPR 32 wrench SONDA CARB. FUAL PROBE
所以你可以看到元素 33 和 34 在元素 32 下面,而元素 32 在元素 13 下面,最后元素 13 没有父元素,因为它是根元素(它的 MNU_PARENT 是 0) . 好吧,我已经将我的代码开发为 return 以下内容:
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
)
)
但是如您所见,我无法在第一层生成正确的结构。换句话说,如果您查看 MNLS 下的 INSTL 元素,则会出现以下错误:
- 项目 MNU_ID、MNU_FUNC、MNU_PARENT 不应该存在(请参阅其他项目)
- '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(
[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
.