Tp5 实现无限分类的复制功能

1. 分析结构

 

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

 

 

 

 

无限分类的算法 可以不看直接调用即可

// 无限分类算法
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);

 

 

2. 复制的思路

 

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

2. 遍历 unset 他们的id

3. saveAll() 批量插入

 

 

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

( 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】)

 

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

 

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

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

 

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

 

 

4. 项目实例

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

 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());
        }

    }
posted @ 2021-08-04 12:31  jaychou、  阅读(55)  评论(0)    收藏  举报