1. 程式人生 > >以一次專案經歷淺談php無限極分類和遞迴的關係

以一次專案經歷淺談php無限極分類和遞迴的關係

專案背景:
新專案是一個分銷系統,核心技術就是無限極分類,每個會員都可以邀請別人進入這個團隊,會員可以升級,可以享受獎勵,前提是不斷地邀請別人加入,這樣每個團隊的長遠可以層層繫結關係。
資料庫設計:

資料庫的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欄位並且記入日誌。程式碼的最後判斷當前父級是否還有父級,這個條件是遞迴的入口條件,不然可能導致遞迴會無限迴圈。 該方法的觸發條件是為當前會員設定父級的時候,下級與上級一一繫結樹狀圖的關係,並在升級的時候和遞迴很好的用到了一起。功能是實現了,考慮效能的話肯定還有更好的方法,在今後的工作與學習中會繼續完善它,表達能力有限,相信自己可以不斷進步。