以一次專案經歷淺談php無限極分類和遞迴的關係
阿新 • • 發佈:2019-02-12
專案背景:
新專案是一個分銷系統,核心技術就是無限極分類,每個會員都可以邀請別人進入這個團隊,會員可以升級,可以享受獎勵,前提是不斷地邀請別人加入,這樣每個團隊的長遠可以層層繫結關係。
資料庫設計:
資料庫的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欄位並且記入日誌。程式碼的最後判斷當前父級是否還有父級,這個條件是遞迴的入口條件,不然可能導致遞迴會無限迴圈。 該方法的觸發條件是為當前會員設定父級的時候,下級與上級一一繫結樹狀圖的關係,並在升級的時候和遞迴很好的用到了一起。功能是實現了,考慮效能的話肯定還有更好的方法,在今後的工作與學習中會繼續完善它,表達能力有限,相信自己可以不斷進步。