以一次项目经历浅谈php无限极分类和递归的关系

项目背景:
新项目是一个分销系统,核心技术就是无限极分类,每个会员都可以邀请别人进入这个团队,会员可以升级,可以享受奖励,前提是不断地邀请别人加入,这样每个团队的长远可以层层绑定关系。
数据库设计:
以一次项目经历浅谈php无限极分类和递归的关系_第1张图片
数据库的user表这样设计,invite_id为邀请人id,parent_id为直接父级id,path表示当前会员在团队里的路径,当前的会员可以通过parent_id一直找到他的父级,直到最顶层。也可以通过parent_id找到他的直接邀请人。
下面以一段代码说明无限极分类和递归的关系:

代码片段:

static function teamUpgrade($parent_id)
    {
        $userObj = new IModel('user');
        $parentRow = $userObj->getObj('id = '.$parent_id);

        //获取children信息
        $childrenObj = new IQuery('user');
        $childrenObj->where = 'parent_id='.$parent_id;
        $childrenObj->fields = 'id,path,group_code';
        $childrenRows = $childrenObj->find();

        //当前用户直接邀请人
        $inviteSum = self::getInviteSum($parent_id);

        //查询当前用户团队人数
        $group_sum = self::getAllTeam($parent_id,$parentRow['path'],$parentRow['group_code']);

        //根据团队总数和直接邀请人数判断是否升级(常规情形)
        switch ($group_sum['group_sum']-1) {
            case 10:
                if ($inviteSum['invite_sum'] >= 2) {
                    $levelTmp = self::teamUpdate($parentRow['level']);
                }
                break;
            case 30:
                if ($inviteSum['invite_sum'] >= 3) {
                    $levelTmp = self::teamUpdate($parentRow['level']);
                }
                break;
            //A区或者B区大于等于30单(最小区大于等于30单)
            case 100:
                if ($childrenRows[0]['path'] && $childrenRows[1]['path'])
                {
                    //A,B区同时存在,并且大于等于30单
                    $aZone = self::getAllTeam($childrenRows[0]['id'],$childrenRows[0]['path'],$childrenRows[0]['group_code']);
                    $bZone = self::getAllTeam($childrenRows[1]['id'],$childrenRows[1]['path'],$childrenRows[1]['group_code']);

                    if($aZone['group_sum']>=30 && $bZone['group_sum']>=30)
                    {
                        $levelTmp = self::teamUpdate($parentRow['level']);
                    }

                }
                break;
            case 300:
                if ($childrenRows[0]['path'] && $childrenRows[1]['path'])
                {
                    //A,B区同时存在,并且大于等于100单
                    $aZone = self::getAllTeam($childrenRows[0]['id'],$childrenRows[0]['path'],$childrenRows[0]['group_code']);
                    $bZone = self::getAllTeam($childrenRows[1]['id'],$childrenRows[1]['path'],$childrenRows[1]['group_code']);

                    if($aZone['group_sum']>=100 && $bZone['group_sum']>=100)
                    {
                        $levelTmp = self::teamUpdate($parentRow['level']);
                    }

                }
                break;
            case 900:
                if ($childrenRows[0]['path'] && $childrenRows[1]['path'] && $childrenRows[2]['path'])
                {
                    //A,B,C区同时存在,最小两边之和大于300单
                    $aZone = self::getAllTeam($childrenRows[0]['id'],$childrenRows[0]['path'],$childrenRows[0]['group_code']);
                    $bZone = self::getAllTeam($childrenRows[1]['id'],$childrenRows[1]['path'],$childrenRows[1]['group_code']);
                    $cZone = self::getAllTeam($childrenRows[2]['id'],$childrenRows[2]['path'],$childrenRows[2]['group_code']);

                    $sum = array($aZone['group_sum'],$bZone['group_sum'],$cZone['group_sum']);
                    array_multisort($sum,SORT_ASC,SORT_NUMERIC);
                    if($sum[0] + $sum[1] >= 300)
                    {
                        $levelTmp = self::teamUpdate($parentRow['level']);
                    }

                }
                break;
            case 2500:
                if ($childrenRows[0]['path'] && $childrenRows[1]['path'] && $childrenRows[2]['path'] && $childrenRows[3]['path'])
                {
                    //A,B,C,D区同时存在,最小三边之和大于900单
                    $aZone = self::getAllTeam($childrenRows[0]['id'],$childrenRows[0]['path'],$childrenRows[0]['group_code']);
                    $bZone = self::getAllTeam($childrenRows[1]['id'],$childrenRows[1]['path'],$childrenRows[1]['group_code']);
                    $cZone = self::getAllTeam($childrenRows[2]['id'],$childrenRows[2]['path'],$childrenRows[2]['group_code']);
                    $dZone = self::getAllTeam($childrenRows[3]['id'],$childrenRows[3]['path'],$childrenRows[3]['group_code']);

                    $sum = array($aZone['group_sum'],$bZone['group_sum'],$cZone['group_sum'],$dZone['group_sum']);
                    array_multisort($sum,SORT_ASC,SORT_NUMERIC);
                    if($sum[0] + $sum[1] + $sum[2]>= 833)
                    {
                        $levelTmp = self::teamUpdate($parentRow['level']);
                    }

                }
                break;
            case 7500:
                if ($childrenRows[0]['path'] && $childrenRows[1]['path'] && $childrenRows[2]['path'] && $childrenRows[3]['path'])
                {
                    //A,B,C,D区同时存在,最小三边之和大于2500单
                    $aZone = self::getAllTeam($childrenRows[0]['id'],$childrenRows[0]['path'],$childrenRows[0]['group_code']);
                    $bZone = self::getAllTeam($childrenRows[1]['id'],$childrenRows[1]['path'],$childrenRows[1]['group_code']);
                    $cZone = self::getAllTeam($childrenRows[2]['id'],$childrenRows[2]['path'],$childrenRows[2]['group_code']);
                    $dZone = self::getAllTeam($childrenRows[3]['id'],$childrenRows[3]['path'],$childrenRows[3]['group_code']);

                    $sum = array($aZone['group_sum'],$bZone['group_sum'],$cZone['group_sum'],$dZone['group_sum']);
                    array_multisort($sum,SORT_ASC,SORT_NUMERIC);
                    if($sum[0] + $sum[1] + $sum[2] >= 2500)
                    {
                        $levelTmp = self::teamUpdate($parentRow['level']);
                    }

                }
                break;
            case 16667:
                if ($childrenRows[0]['path'] && $childrenRows[1]['path'] && $childrenRows[2]['path'] && $childrenRows[3]['path'])
                {
                    //A,B,C,D区同时存在,最小三边之和大于5000单
                    $aZone = self::getAllTeam($childrenRows[0]['id'],$childrenRows[0]['path'],$childrenRows[0]['group_code']);
                    $bZone = self::getAllTeam($childrenRows[1]['id'],$childrenRows[1]['path'],$childrenRows[1]['group_code']);
                    $cZone = self::getAllTeam($childrenRows[2]['id'],$childrenRows[2]['path'],$childrenRows[2]['group_code']);
                    $dZone = self::getAllTeam($childrenRows[3]['id'],$childrenRows[3]['path'],$childrenRows[3]['group_code']);

                    $sum = array($aZone['group_sum'],$bZone['group_sum'],$cZone['group_sum'],$dZone['group_sum']);
                    array_multisort($sum,SORT_ASC,SORT_NUMERIC);
                    if($sum[0] + $sum[1] + $sum[2] >= 5000)
                    {
                        $levelTmp = self::teamUpdate($parentRow['level']);
                    }

                }
                break;
            default:
                # code...
                break;
        }
        /*****非常规情况下的升级结束*****/

        //等级升级和轨道升级
        if($levelTmp)
        {
            //当升级为区代理时,升级为三个轨道,升级为市代理时,升级为四个轨道
            if($levelTmp == 22)
            {
                $pathway=3;
            }
            if($levelTmp == 23)
            {
                $pathway=4;
            }
            if($pathway)
            {
                $userObj->setData(array('level'=>$levelTmp,'pathway'=>$pathway));
            }
            else
            {
                $userObj->setData(array('level'=>$levelTmp));
            }
            $res = $userObj->update('id = '.$parent_id);
        }

        //不管是否升级成功,都有等级奖励并写入日志
        // $parentRow = $userObj->getObj('id = '.$parent_id);//重新查询,等级可能有变动
        // $levelTmp = $parentRow['level'];
        // $award = self::levelAward($levelTmp);

        //添加等级奖励写入日志(不管是否升级)
        // self::addAward($parent_id,$levelTmp,$award);

        //当前等级下的其他等级如果没有,奖励归当前等级所有
        // self::addPlusAward($parent_id);

        //写入升级日志(不计算奖励)
        if($levelTmp)
        {
            self::upgradeLog($parent_id,$levelTmp);
        }

        *****//判断父级的父级,存在则递归计算
        if($parentRow['parent_id']==0){
            //没有父级,直接退出
            return;
        }
        //有父级,回调自身继续计算
        if($parentRow['parent_id']>0)
        {
            self::teamUpgrade($parentRow['parent_id']);
        }*****

    }

总结:
代码的主要逻辑是判断父级是否满足升级的条件,满足的话去更新user表的level字段并且记入日志。代码的最后判断当前父级是否还有父级,这个条件是递归的入口条件,不然可能导致递归会无限循环。 该方法的触发条件是为当前会员设置父级的时候,下级与上级一一绑定树状图的关系,并在升级的时候和递归很好的用到了一起。功能是实现了,考虑性能的话肯定还有更好的方法,在今后的工作与学习中会继续完善它,表达能力有限,相信自己可以不断进步。

你可能感兴趣的:(php)