jjzjj

php - 从 SQL 查询结果构建父/子数组菜单结构

coder 2024-05-05 原文

我需要使用 MySQL 数据库查询以动态方式构建复杂的菜单结构。该查询允许定义用户有权使用和查看的菜单项。 Menu 结构以经典的父/子关系存储到结果集中,其中每个元素都有自己的 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)。 好吧,我已经开发了我的代码以返回以下内容:

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 元素,则会出现以下错误:

  1. 项目 MNU_ID、MNU_FUNC、MNU_PARENT 不应该存在(查看其他项目)
  2. 'sub' 下的项目在 1 中有相同的错误。
  3. '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);

关于php - 从 SQL 查询结果构建父/子数组菜单结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48278225/

有关php - 从 SQL 查询结果构建父/子数组菜单结构的更多相关文章

  1. ruby - ECONNRESET (Whois::ConnectionError) - 尝试在 Ruby 中查询 Whois 时出错 - 2

    我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.

  2. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  3. ruby-on-rails - 在 Rails 和 ActiveRecord 中查询时忽略某些字段 - 2

    我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr

  4. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

  5. 报告回顾丨模型进化狂飙,DetectGPT能否识别最新模型生成结果? - 2

    导读语言模型给我们的生产生活带来了极大便利,但同时不少人也利用他们从事作弊工作。如何规避这些难辨真伪的文字所产生的负面影响也成为一大难题。在3月9日智源Live第33期活动「DetectGPT:判断文本是否为机器生成的工具」中,主讲人Eric为我们讲解了DetectGPT工作背后的思路——一种基于概率曲率检测的用于检测模型生成文本的工具,它可以帮助我们更好地分辨文章的来源和可信度,对保护信息真实、防止欺诈等方面具有重要意义。本次报告主要围绕其功能,实现和效果等展开。(文末点击“阅读原文”,查看活动回放。)Ericmitchell斯坦福大学计算机系四年级博士生,由ChelseaFinn和Chri

  6. ruby - 在 Ruby 中构建长字符串的简洁方法 - 2

    在编写Ruby(客户端脚本)时,我看到了三种构建更长字符串的方法,包括行尾,所有这些对我来说“闻起来”有点难看。有没有更干净、更好的方法?变量递增。ifrender_quote?quote="NowthatthereistheTec-9,acrappyspraygunfromSouthMiami."quote+="ThisgunisadvertisedasthemostpopularguninAmericancrime.Doyoubelievethatshit?"quote+="Itactuallysaysthatinthelittlebookthatcomeswithit:themo

  7. Hive SQL 五大经典面试题 - 2

    目录第1题连续问题分析:解法:第2题分组问题分析:解法:第3题间隔连续问题分析:解法:第4题打折日期交叉问题分析:解法:第5题同时在线问题分析:解法:第1题连续问题如下数据为蚂蚁森林中用户领取的减少碳排放量iddtlowcarbon10012021-12-1212310022021-12-124510012021-12-134310012021-12-134510012021-12-132310022021-12-144510012021-12-1423010022021-12-154510012021-12-1523.......找出连续3天及以上减少碳排放量在100以上的用户分析:遇到这类

  8. ruby-on-rails - 一般建议和推荐的文件夹结构 - Sinatra - 2

    您将如何构建一个简单的Sinatra应用程序?我正在制作,我希望该应用具有以下功能:“应用程序”更像是一个包含所有信息的管理仪表板。然后另一个应用程序将通过REST访问信息。我还没有创建仪表板,只是从数据库中获取东西session和身份验证(尚未实现)您可以上传图片,其他应用可以显示这些图片我已经使用RSpec创建了一个测试文件通过Prawn生成报告目前的设置是这样的:app.rbtest_app.rb因为我实际上只有应用程序和测试文件。到目前为止,我已经将Datamapper用于ORM,将SQLite用于数据库。这是我的第一个Ruby/Sinatra项目,所以欢迎任何和所有建议-我应

  9. sql - 查询忽略时间戳日期的时间范围 - 2

    我正在尝试查询我的Rails数据库(Postgres)中的购买表,我想查询时间范围。例如,我想知道在所有日期的下午2点到3点之间进行了多少次购买。此表中有一个created_at列,但我不知道如何在不搜索特定日期的情况下完成此操作。我试过:Purchases.where("created_atBETWEEN?and?",Time.now-1.hour,Time.now)但这最终只会搜索今天与那些时间的日期。 最佳答案 您需要使用PostgreSQL'sdate_part/extractfunction从created_at中提取小时

  10. ruby - 使用 rbenv 和 ruby​​-build 构建 ruby​​ 失败,出现 undefined symbol : SSLv2_method - 2

    我正在尝试在配备ARMv7处理器的SynologyDS215j上安装ruby​​2.2.4或2.3.0。我用了optware-ng安装gcc、make、openssl、openssl-dev和zlib。我根据README中的说明安装了rbenv(版本1.0.0-19-g29b4da7)和ruby​​-build插件。.这些是随optware-ng安装的软件包及其版本binutils-2.25.1-1gcc-5.3.0-6gconv-modules-2.21-3glibc-opt-2.21-4libc-dev-2.21-1libgmp-6.0.0a-1libmpc-1.0.2-1libm

随机推荐