PHP实现无限级分类(递归+引用)

原始数据

  • 数据库

    image
  • 打印到页面

    image

递归

  • 递归的思路就是【找儿子】,也就是循环所有数据,找到每条数据的所有儿子、儿子的儿子、儿子的儿子的儿子....,首先我们知道要找test1的儿子就是找所有pid为1的数据,于是遍历整个数组找到了test1-1和test1-2;然后还要分别找test1-1和test1-2的儿子,就这样一直找下去,由于每次找儿子的方法都是一样的,就是遍历所有数据(除开自己的长辈,因为长辈不可能是儿孙),找出符合条件的,唯一不同的就是每次找儿子的爹不一样,代码如下:
function getChild($data, $id = 0)
    {
        //初始化儿子
        $child = [];
        //循环所有数据找$id的儿子
        foreach ($data as $key => $datum) {
            //找到儿子了
            if ($datum['pid'] == $id) {
                //保存下来,然后继续找儿子的儿子
                $child[$datum['id']] = $datum;
                //先去掉自己,自己不可能是自己的儿孙
                unset($data[$key]);
                //递归找,并把找到的儿子放到一个child的字段中
                $child[$datum['id']]['child'] = $this->getChild($data, $datum['id']);
            }
        }
        return $child;
    }

运行结果:

image

引用

  • 引用确实是一个非常巧妙的方法,也不用像递归那样循环那么多次,思路就是首先把所有数据以id为索引重新排列,排列之后长这个样子:

    image
  • 然后重点来啦!!!然后只需要找到根节点,也就是pid是0的三条数据,把它们放到一个全新的数组中,注意:这里的放并不是简单的赋值,而是引用之前的地址。这两者有什么不同呢,这里简单几个例子说明一下:

    function test(){
        $a=1;
        $b=$a;  //赋值
        $b1=&$a;//赋址
        $a=2;
        dump('$b的值是:'.$b);
        dump('$b1的值是:'.$b1);
    }

最开始$a初始化为1,把$a的值(也就是1)赋给变量$b,然后把$a的地址(内存地址)赋给$b1,然后改变$a的值,再查看$b$b的值。结果如下:

image

我们发现$b的值还是1,而$b1的值却跟随着$a的改变而改变了,这就是因为$b保存的是$a的地址,无论$a怎么变他们的值都会保持一致。
回到我们之前的问题上来,我们用新的数组保存了根节点的地址,后面无论根节点怎么变我们的新数组都会和变化过后的数据保持一致;那么不是根节点的数据怎么处理呢,我们这里可以把它的地址放到他爹的儿子节点当中,这样的话就是一层层引用,最后所有的数据都被新数组引用了。
说了这么多,代码如下:

function getChild($data)
    {
        $tree = [];
        $newData = [];
        //循环重新排列
        foreach ($data as $datum) {
            $newData[$datum['id']] = $datum;
        }
        foreach ($newData as $key => $datum) {
            if ($datum['pid'] > 0) {
                //不是根节点的将自己的地址放到父级的child节点
                $newData[$datum['pid']]['child'][] = &$newData[$key];
            } else {
                //根节点直接把地址放到新数组中
                $tree[] = &$newData[$datum['id']];
            }
        }
        return $tree;
    }

运行结果:

image

参考文档

https://www.cnblogs.com/vishun/p/6716483.html

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 原始数据 数据库原始数据 打印到页面原始数据 递归 递归的思路就是【找儿子】,也就是循环所有数据,找到每条数据的所...
    孤城浪子55555阅读 6,888评论 0 7
  • 程序设计中常使用树型结构来表征某些数据的关联关系,如上下级、栏目结构、商品分类、菜单、回复等。 分类的层级关系可以...
    JunChow520阅读 4,125评论 4 3
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,136评论 1 32
  • 在C语言中,五种基本数据类型存储空间长度的排列顺序是: A)char B)char=int<=float C)ch...
    夏天再来阅读 3,402评论 0 2
  • 这是16年5月份编辑的一份比较杂乱适合自己观看的学习记录文档,今天18年5月份再次想写文章,发现简书还为我保存起的...
    Jenaral阅读 2,831评论 2 9