1. 程式人生 > >使用thinkphp搞了一個簡單的三級分銷

使用thinkphp搞了一個簡單的三級分銷

關於為何要寫-分銷

第一次看到這個分銷這個詞的時候,腦海裡就蹦出了傳銷,在新聞聯播等等媒體的傳播下,讓我對其有著極奇的排斥和生惡的感覺,傳銷固然可惡,但在三級分銷下國家還是允許的,好吧!工具是給人用的,是作惡還是行善,在於的是使用人的思量。為什麼要寫它,還不是領導有要求的,沒辦法人家有需求,那就先寫個試試手吧!

第一步是先思考下邏輯

所謂的分銷就是成員與成員的層級關係,與寫評論功能的時候評論人和回覆人的關係差不多吧!每個評論都可以有無數個回覆者,我要做的就是在知道其中一個成員的情況下知道它的“爸爸”或“爺爺”是誰就行了,剛開始是想在user表中加個父級成員的欄位,然後就可以用遞迴的方法知道它的祖宗十八代了,好吧怎麼感覺在寫族譜呢?最後我還是拋棄了這個想法,因為我用的是mysql資料庫,這麼頻繁的訪問操作資料庫,由於成員數量可能成指數增長,我不敢想象這將對我的電腦造成多大的負擔,誰要是拿這樣的程式碼去執行,嘿嘿!好期待結果是怎麼樣!行吧,我的執行環境直接用的是phpStudy搭建的本地環境,用thinkcmf5.0一鍵生成了可以用的站點,不用自己再寫後臺會員中心什麼的了。

  1. 先建個表吧,用來存放層級關係,開始寫程式碼後,發現還要有各個成員的一些資訊,本來可以多表分級查詢的,但是為了省事,我一股腦的放在一個表裡了,到時直接一個id,要什麼就拿什麼,犧牲空間,換來了更少的程式碼,還是很划算的,至於效能呵呵就行。
    三級分銷表結構
    感覺自己的命名有點問題,可我也懶的深究了。大概的表結構就這樣吧。應該可以用~~
  2. 找到個人使用者中心,直接用後臺管理員的使用者就可以登上去了。至於前端頁面什麼的就不寫了。。
  3. 直接上程式碼吧,不寫廢話了:
    根目錄\app\user\controller\DistributeController.php
public function index(){
     $distribute
= new DistributeModel(); $data = $distribute->level_one(); //在模型裡具體實現資料庫操作 $user = cmf_get_current_user(); //獲取前臺當前登入使用者資訊,如果沒有登,就返回空 $this->assign($user); //cmf自帶的模板分頁渲染方法,將獲取分類好陣列傳給前端去處理 /* 兒級 */ $this->assign("page", $data['page']);//當前頁碼 $this
->assign("lists", $data['lists']); //所有的資料及分類 /* 孫級 */ $this->assign("page2", $data['page2']); $this->assign("lists2", $data['lists2']); /* 曾孫級 */ $this->assign("page3", $data['page3']); $this->assign("lists3", $data['lists3']); return $this->fetch('index'); } /** * @Notes:查詢下一級的成員 */ public function next(){ $distribute = new DistributeModel(); //獲取前端傳來的引數,這是當前兒子成員,當兒子成為父級,那它的兒子自然是之前父級成員的孫子,也就是下一級了 $distribute = new DistributeModel(); $id = $this->request->param("user_id", 0, "intval"); $data = $distribute->next_distribute($id); $user = cmf_get_current_user(); $this->assign($user); /* 一級 */ $this->assign("page", $data['page']); $this->assign("lists", $data['lists']); /* 二級 */ $this->assign("page2", $data['page2']); $this->assign("lists2", $data['lists2']); /* 三級 */ $this->assign("page3", $data['page3']); $this->assign("lists3", $data['lists3']); return $this->fetch('index'); } /** * @Notes:取消層級關係 */ public function negate(){ $data = $this->request->param(); $distribute = new DistributeModel(); //看看獲取到的引數是幾號,畢竟如果父親拒絕兒子的供養,不代表爺爺也願意,所以更新下表欄位就行,將父級id改成0就行了。 $ret = $distribute->negate_distinct($data['id'],$data['negate_obj']);//$data['negate_obj']:1父級;2祖級;3太級; if ($ret) { $this->success("取消關係成功!你再也獲取不到他的分成了!"); } else { $this->error("取消失敗了!"); } }

下面是模型程式碼了:

 public function level_one($data = null)
    {
        $oneself_id = cmf_get_current_user_id(); //獲取當前使用者的id
        $oneself = Db::name('distribute');
        /* 一級 */
        $level_one = $oneself->where(['father_id' => $oneself_id])->order('id desc')->paginate(10);
        $data['page'] = $level_one->render();
        $data['lists'] = $level_one->items();
        /* 二級 */
        $level_two = $oneself->where(['grandpa_id' => $oneself_id])->order('id desc')->paginate(10);
        $data['page2'] = $level_two->render();
        $data['lists2'] = $level_two->items();
        /* 三級 */
        $level_there = $oneself->where(['great_grandpa_id' => $oneself_id])->order('id desc')->paginate(10);
        $data['page3'] = $level_there->render();
        $data['lists3'] = $level_there->items();

        return $data;
    }

    /**
     *   @Notes: $negate_obj ?=1(父級:father) ?=2(祖級:grandpa) ?=3(太級:great_grandpa)
     */
    public function negate_distinct($id, $negate_obj)
    {
        switch ($negate_obj) {
            case 1:
                $obj = 'father_id';
                break;
            case 2:
                $obj = 'grandpa_id';
                break;
            case 3:
                $obj = 'great_grandpa_id';
                break;
            default:
                return false;
        }
        $ret = Db::name('distribute')->where('id', $id)->update([$obj => 0]);
        return $ret;
    }

    /**
     *   @Notes:有點的冗餘了,不過可以讓的邏輯清楚些,用來知道子級,
     * 用遞迴應該可以實現無限級分銷,
     * 但是這個應該是違法的,不過拿去用做無級分類還是很好的嘛。
     */
    public function next_distribute($id){
     $oneself = Db::name('distribute');
   	  /* 一級 */
      $level_one = $oneself->where(['father_id' => $id])->order('id desc')->paginate(10);
      $data['page'] = $level_one->render();
      $data['lists'] = $level_one->items();
      /* 二級 */
      $level_two = $oneself->where(['grandpa_id' => $id])->order('id desc')->paginate(10);
      $data['page2'] = $level_two->render();
      $data['lists2'] = $level_two->items();
      /* 三級 */
      $level_there = $oneself->where(['great_grandpa_id' => $id])->order('id desc')->paginate(10);
      $data['page3'] = $level_there->render();
      $data['lists3'] = $level_there->items();
      return $data;
    }

基本上就這些了,後面就是對各級的分成進行劃分了。

第二步是要獲取層級關係寫入表中

  1. 打算在第三步的時候,直接在域名地址後面加引數,可以用get方法取到值了,所以現在假設有個地址直接是指向註冊頁面的,後面還跟個它的推薦人的id號,這樣就不用在註冊資訊裡讓使用者手動填寫它的推薦人是哪個了,萬一這個使用者來到註冊頁面沒有註冊而是去首頁看看的話,嗯!?好吧可能性很大,所以我就先將獲取到的引數存到cookie中就行了,一天後失效。使用者註冊成功後,再看看有沒有父級,為了以後測試,給每個註冊成功的使用者贈送100個積分,隨便給其推薦人獎勵一些積分,後面是程式碼了
  • 這段直接插在註冊頁面控制器裡的:
 /* 獲取邀請碼 ,並轉存下,簡單明瞭 */
  $request = $this->request->get('invite_key');
    if($request){
        setcookie("invite_key", $request, time()+(3600*24));
    }
  • 然後找到其模型方法裡,在各類驗證完成後加上獲取推薦碼方法:
	/**
     *   @Notes: 獲取邀請碼,如果沒有就不做處理,有的話將資料寫入層級關係表裡面distribute
     */
    public function collect_invite($userId = null,$name = null)
    {
        $request = Request::instance();//都封裝在\think\Request,上面use下
        $invite_key = $request->get('invite_key');
        if (empty($invite_key)) {
        //這裡好像有點囉嗦,但是可以預防可能多種不確定情況,可能吧!我也不知道
            $invite_key = $request->cookie('invite_key');
        }
        if (!empty($invite_key)) {
            $ret = Db::name('distribute')->where('user_id',$invite_key)->find();
            if($ret){
        //咱不用時間戳,雖然這樣可能發生時區問題,可是這僅僅是給我自己看的方便,所以就無視吧。
                $time = date("Y-m-d H:i:s",time());
                $data = [
                    'user_id' => $userId,
                    'father_id' => empty($ret['user_id'])?'':$ret['user_id'],
                    'grandpa_id' => empty($ret['father_id'])?'':$ret['father_id'],
                    'great_grandpa_id' => empty($ret['grandpa_id'])?'':$ret['grandpa_id'],
                    'create_time' => $time,
                    'user_name' => empty($name)?'':$name,
                    'father_name' => empty($ret['user_name'])?'':$ret['user_name'],
                    'grandpa_name' => empty($ret['father_name'])?'':$ret['father_name'],
                    'great_grandpa_name' => empty($ret['grandpa_name'])?'':$ret['grandpa_name'],
                ];
                Db::name('distribute')->insert($data);
            }else{return false;}

       }else{return false;}
    }

層級關係什麼的已經找到了,下面就是獎勵積分了,人人有份啊!在那之前去加個新表吧!
1.積分操作日誌表:
積分操作日誌表
2.如果user表中沒有積分欄位的話,就去加個。順便我加了個推薦碼欄位,目前用不到,可是第三步應該用到。下面的程式碼有點多,有點雜,我自己寫完後也都不想看了~~

    /**		
     *   @Notes:給新註冊的使用者贈送些積分,順便給其父級們獎勵下些
     */
    public function share_out($user_id){
        $share_data = Db::name('share_out')->select();//這個用來給後臺設定分成百分比的
        if(!$share_data){//可能是空的,如果是的話提醒下我自己
            $time = time();
            $china_time = date("Y-m-d H:i:s",time());
            $result = 'share_out,這個表資料已經不能用了';
            $address = cmf_asset_relative_url();
            $data=[
                'time' => $time,
                'china_time' => $china_time,
                'result' => $result,
                'address' => $address,
            ];
            Db::name('error_log')->insert($data);//感覺很多餘,應該是沒用的東西
        }
        $data_user = Db::name('user')->where('id',$user_id)->find();
        if($data_user){
            $data = $data_user['score'] + 100; //在這裡給註冊使用者加積分
            Db::table('user')->where('id', $user_id)->update(['score' => $data]);
        }else{
            $time = time();
            $china_time = date("Y-m-d H:i:s",time());
            $result = '給新註冊使用者贈送一些積分的時候出錯了';
            $address = cmf_asset_relative_url();
            $data=[
                'time' => $time,
                'china_time' => $china_time,
                'result' => $result,
                'address' => $address,
            ];
            Db::name('error_log')->insert($data);
        }
        //後面是給推薦人們分的積分
        //先去層級關係中查好關係
        $data_out = Db::name('distribute')->where(