【问题标题】:Cannot create deep level menu无法创建深层菜单
【发布时间】:2021-08-18 21:12:41
【问题描述】:

我正在尝试创建一个深层菜单,所以我在我的数据库中定义了这个表结构:

id | parent | menu_order
15      0         0
22     15         0
26     15         0
30     15         0
47     22         0
49     22         0
51     22         0
68     26         0
69     26         0

我想要实现的是生成允许我正确设置menu_order 列的代码,在上面的示例中,最终结果应该是:

id | parent | menu_order
15     0          0
22     15         1
26     15         5
30     15         8
47     22         2
49     22         3
51     22         4
68     26         6
69     26         7

结果很容易理解,基本上22parent 15,所以menu_order1。相同的概念适用于22 的嵌套级别,即(47,49,51)。

其实我的代码是这样的:

<?php

$posts = [
    ['id' => 15, 'parent' => 0, 'menu_order' => 0],
    ['id' => 22, 'parent' => 15, 'menu_order' => 0],
    ['id' => 26, 'parent' => 15, 'menu_order' => 0],
    ['id' => 30, 'parent' => 15, 'menu_order' => 0],
    ['id' => 47, 'parent' => 22, 'menu_order' => 0],
    ['id' => 49, 'parent' => 22, 'menu_order' => 0],
    ['id' => 51, 'parent' => 22, 'menu_order' => 0],
    ['id' => 68, 'parent' => 26, 'menu_order' => 0],
    ['id' => 69, 'parent' => 26, 'menu_order' => 0],
];

$currOrder = -1;

 foreach ($posts as $key => $p) {

    $currOrder++;

    $test[] = [
        'id'    => $p['id'],
        'parent' => $p['parent'],
        'menu_order' => $currOrder
    ];

    hasChild($p['id'], $currOrder, $test);
}

    
function hasChild($postId, &$currOrder, $test)
{
    // get childs post
    $childs = $this->where('parent', $postId)
        ->get()
        ->getResult();

    foreach ($childs as $c) {

        $currOrder++;
        
        $test[] = [
            'id'    => $c['id'],
            'parent' => $c['parent'],
            'menu_order' => $currOrder
        ];

         // check nested levels
        if ($c->parent != 0) {
           hasChild($c['id'], $currOrder, $test);
        }
    }
}

问题是我得到了嵌套级别的重复帖子,而menu_order 完全搞砸了。我想我的逻辑过于复杂,有人可以帮我实现这个吗?

谢谢

【问题讨论】:

    标签: php mysql codeigniter-4


    【解决方案1】:

    有几种方法可以处理递归函数。我就是这样做的。

    <?php
    // example code
    
    $posts = [
        ['id' => 15, 'parent' => 0, 'menu_order' => 0],
        ['id' => 22, 'parent' => 15, 'menu_order' => 0],
        ['id' => 26, 'parent' => 15, 'menu_order' => 0],
        ['id' => 30, 'parent' => 15, 'menu_order' => 0],
        ['id' => 47, 'parent' => 22, 'menu_order' => 0],
        ['id' => 49, 'parent' => 22, 'menu_order' => 0],
        ['id' => 51, 'parent' => 22, 'menu_order' => 0],
        ['id' => 68, 'parent' => 26, 'menu_order' => 0],
        ['id' => 69, 'parent' => 26, 'menu_order' => 0],
    ];
    
    
    function recursePosts($pid, $order, $tally, $posts) {
        foreach($posts as $p) {
            if ($p['parent']===$pid) {
                $p['menu_order'] = $tally  ;
                $order['id'.$p['id']] = $p;
                $tally++;
                $o = recursePosts($p['id'], $order, $tally, $posts);  
                $tally = $o[1];
                $order = $o[0];
            }
            
        }
        return [$order, $tally];
    }
    $o =recursePosts(0, [], 0, $posts);
    $order = $o[0];
    ksort($order);
    print_r(array_values($order));
    

    https://www.tehplayground.com/uNY7Bn0VyDv6JIUS

    还有PHP原生的RecursiveIterator

    【讨论】:

    • 感谢似乎有效!只是一个问题:我有一个对象数组,所以我做了一些小改动:$order[] = $p; 而不是$order['id' . $p-&gt;id] = $p;。当我开始迭代它时,我得到:array(36) { [0]=&gt; object(stdClass)#107 (16) { ["id"] 如何直接推送项目?
    • 我为每个数组放那个假密钥的原因是我可以在最后对它进行排序。您的示例输出显示它是按 id 排序的。 ksort() 根据那些 id36 键对数组进行排序,array_values 最后将它们删除,因此最终结果与 $order[]= 相同,只是排序。这有意义吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-18
    • 2013-09-22
    • 1970-01-01
    • 2021-12-06
    • 1970-01-01
    相关资源
    最近更新 更多