tp5.1实现扁平转树状无限分类的复制功能

分析结构

先看数据库 ( 第二个字段是用于联表操作 可以忽略 )

tp5.1实现扁平转树状无限分类的复制功能_第1张图片

tp5.1实现扁平转树状无限分类的复制功能_第2张图片

扁平转树状

// 无限分类算法
function listTree($list, $pk = 'id', $pid = 'pid', $child = 'children', $root = 0)
{

    if (!is_array($list)) {
        return [];
    }
    //创建基于主键的数组引用
    $aRefer = [];
    $tree = [];
    foreach ($list as $k => $v) {
        $aRefer[$v[$pk]] = &$list[$k];  // 主键id 作为数组下标
    }

    foreach ($list as $k => $v) {

        //判断是否存在parent
        $parentId = $v[$pid];
        if ($root === $parentId) {      // 当父id = 0 则是最外层
            $tree[] = &$list[$k];
        } else {                        // 当父id != 0 就创建 孩子层
            if (isset($aRefer[$parentId])) {    // 当该数据 的父亲数据存在时

                $parent = &$aRefer[$parentId];
                $parent[$child][] = &$list[$k]; // 为该父亲创建一个孩子层数据,孩子层数据就是该数据本身
            }
        }
    }
    return $tree;
}

测试 记得->toArray()

$list = $this->detail->where(['planpvc_id' => $planpvc_id])->field($field)->select()->toArray();  
$data = listTree($list);    // 转为无限分类
return json($data);

tp5.1实现扁平转树状无限分类的复制功能_第3张图片

实现复制的思路

  1. 先查询出要复制的无限分类

  2. 遍历 unset 他们的id

  3. saveAll() 批量插入

  4. 如果是像我这个项目这样,涉及到联表的,那么思路如下**

tp5.1实现扁平转树状无限分类的复制功能_第4张图片

( 1 是父表 n是子表 )

  1. 先查询出要复制的父表的内容 a

  2. unset() a 的主键 oldId,然后插入到父表 ,得到新id newId

  3. 查询子表 planpvc_id = oldId 的数据 b (通过layer 升序查询)

  4. 使用遍历把 b 里面的planpvc_id 换成 newId

  5. 使用遍历 + if 判断 , 并创建数组 存放无限分类 第一层、第二层的id, topId_arr ndId_arr

( 数组格式是 【旧数据的id】=> 【新数据的id】)

  1. if(pid = 0) 则是最外层,插入数据到子表,并且把插入后的id 放到 topId_arr

  2. if(layer = 2) 则是第二层,pid = topId_arr [ 旧的pid ] , 因为第二层旧的 pid ==
    第一层旧的pid

    插入数据到子表,并且把插入后的id 放到 ndId_arr

  3. if(layer= 3) 则是第三层,pid =ndId_arr [ 旧的pid ], 插入数据到子表

4. 项目实例

ps: 下面是参考代码,这次项目主要联表有点多会用到多个遍历, 所以大家可以从 3.clone 到详情表 开始看

tp5.1实现扁平转树状无限分类的复制功能_第5张图片

 public function copy()
    {
     
        $id = input('plan_id');
        $title = input('title');
        if (!is_numeric($id) || strlen($title) < 3)
            return failApi('参数错误');

        $planProvince = new ErPlanProvince();
        $detail = new ErDetail();
        Db::startTrans();
        try {
     
            // 1. clone 到计划表
            $this->plan->save(['title' => $title]);     // clone
            $plan_id = $this->plan->id;     // clone 后的plan_id

            // 2. clone 到省份表
            $pvc_arr = $planProvince->where(['plan_id' => $id])->field('create_time,update_time', true)->select()->toArray();

            if (!count($pvc_arr))
                return failApi("无省份数据");

            // 交换id
            array_walk($pvc_arr, function (&$v, $k) use (&$oldPvcId_arr, $plan_id) {
     

                $v['plan_id'] = $plan_id;   // 换成clone 后的plan_id
                $oldPvcId_arr[] = $v['id'];           // 获取旧的的 planpvc_id
                unset($v['id']);
            });

            $ins_arr = $planProvince->saveAll($pvc_arr);    // clone

            foreach ($ins_arr as $k => $v) {
     
                //  key:  old_id    value : new_id
                $old_new_PvcID[$oldPvcId_arr[$k]] = $v['id'];   // 获取clone后的 planpvc_id
            }

            unset($ins_arr);
            unset($pvc_arr);

            // 3. clone 到详情表

            array_walk($oldPvcId_arr, function ($oldId, $keys) use ($detail, $old_new_PvcID, &$detail_arr) {
     

                // 1.根据 planpvc_id 查看每个省是否有详情信息
                $detail_arr = $detail->where('planpvc_id', $oldId)->order('layer inc')->field('create_time,update_time', true)->select()->toArray();

                if (count($detail_arr)) {
                        // detail表有数据
//
                    $topIdArr = [];  // 存放顶层id
                    $ndIdArr = [];   // 存放二级的id

                    array_walk($detail_arr, function (&$v, $key) use ($old_new_PvcID, $oldId, $detail, &$topIdArr, &$ndIdArr) {
          // 2.该planpvc_id 下的detail数据:

                        $v['planpvc_id'] = $old_new_PvcID[$oldId];   // 3. 赋上新的planpvc_id

                        if ($v['pid'] == 0) {
                       // 最外层id

                            $detail->create(['planpvc_id' => $v['planpvc_id'], 'pid' => $v['pid'], 'title' => $v['title'], 'count' => $v['count'], 'layer' => $v['layer']]);
                            $topIdArr[$v['id']] = $detail->getLastInsID();   // 存入最高层的 id  旧Id => 新Id
                            // dump($topIdArr) ;
                        }
                        if ($v['layer'] == 2) {
                   // 第二层

                            $v['pid'] = $topIdArr[$v['pid']];    // 查找最高层id
                            $detail->create(['planpvc_id' => $v['planpvc_id'], 'pid' => $v['pid'], 'title' => $v['title'], 'count' => $v['count'], 'layer' => $v['layer']]);
                            $ndIdArr[$v['id']] = $detail->getLastInsID();   // 存入第二层的 id  旧Id => 新Id
                            //dump($ndIdArr);
                        }
                        if ($v['layer'] == 3) {
           // 底层

                            $v['pid'] = $ndIdArr[$v['pid']];    // 查找第二层id
                            $detail->create(['planpvc_id' => $v['planpvc_id'], 'pid' => $v['pid'], 'title' => $v['title'], 'count' => $v['count'], 'layer' => $v['layer']]);
                        }
                        unset($v['id']);
                    });
                }

            });

            Db::commit();
            return sucApi('复制成功');
        } catch (Exception $e) {
     
            Db::rollback();
            failApi($e->getMessage());
        }

    }

你可能感兴趣的:(PHP,mysql,php,thinkphp)