1. 程式人生 > >此次商城專案中‘購物車’模組總結

此次商城專案中‘購物車’模組總結

購物車模組前期分析

1.首先我們可以根據session('user_id'),看是否能夠獲取到使用者的標識id,能夠獲取到,說明使用者已經登入,接下來我們對相應的購物車資料表進行操作;如果沒有獲取到使用者標識id,則說明使用者沒有登入,接下來我們就操作cookie(這裡我們選擇的cookie,也可以選擇session,redis);

2.建表:包含欄位->(id , user_id , goods_id , goods_attr_ids , goods_count),對於同一個商品屬性組合相同直接增加購買數量即可。對於屬性組合不一樣,需要單獨的使用資料記錄 ;

3.對於cookie儲存資料需要跟資料庫的儲存一致需要記錄到對應的商品ID、屬性組合以及購買數量。因此對應的資料就是一個數組格式但是目前cookie只能支援字串的格式 , 可以將陣列格式轉換為字串的格式 可以通過使用序列化或者使用json格式儲存 , 這裡我在專案中選擇的是序列化方式,這樣直接將資料進行序列與反序列更為方便 ;

4.因為在每次新增商品進入購物車時都需要檢查商品跟屬性組合對應的資訊是否存在。如果存在直接更新購買數量,否則再次增加對應的資料,可以通過對key設定為一個有規律的值來方便判斷,可以將key的設定為:商品ID-屬性組合作為key

Array( ‘2-20,25’=>2,‘2-22,25’=>1 )

使用此方式就大大的簡化了cookie的資料判斷操作;

可以忽略程式碼

加入購物車()

3,4兩小點為核心步驟

  1. 商品詳情頁,當用戶點選‘加入購物車’時,呼叫購物車控制器的add方法(實現商品新增到購物車),在add方法接收對應的goods_id,goods_count,goods_attr_ids , 然後呼叫購物車模型中的新增購物車方法(將接收的商品id,商品數量,商品屬性組合資訊傳遞過去),---(

    這裡我們需要注意,修改表單實現屬性的提交,因為商品屬性需要多個值提交因此在商品屬性name使用陣列格式,但是由於每一個屬性值都是對應的radio因此需要手動指定具體的下標資訊,使用屬性值得id作為標識);

  2. 在購物車模型,首先指定自定義欄位資訊(具體好處,可自己看文件),然後定義新增購物車方法:先將屬性資訊做一個從小到大的排序 目的就是為了後期庫存量的檢查sort($attr),然後進行庫存量的檢查(該方法已經封裝好),再獲取使用者id->session('user_id'),進行判斷使用者是否判斷;

  3. 如果存在user_id說明使用者已經登入,接下來的操作去操作資料表,然後根據當前要寫入的資料資訊 判斷資料庫是否已存在,如果存在直接更新對應的數量 否則直接寫入即可,那麼如何進行判斷,我們可以將商品id,使用者id,商品屬性id組合拼裝成一個數組作為條件,在購物車資料表進行查詢;

  4. 如果user_id不存在,說明使用者沒有登入,則對應操作cookie中的資料,首先取出cookie中的購物車資訊,此時為字串,我們可以反序列化為一個數組,然後將我們拿到的商品和商品屬性組合以形式進行拼接key,然後那這個拼接的資訊去與我們反序列化得到的陣列的下標進行比較array_key_exists(cart),如果拼裝的key在反序列化的陣列的下標中存在,說明目前新增的商品資訊已經存在,就直接更新購物車中的商品數量;否則,直接將購物車資料寫入cookie,寫入前,需將資料進行反序列化為字串,然後再寫入cookie('cart',serialize($cart));

具體程式碼流程:


 //作用就是實現具體商品資訊加入到購物車
    public function addCart($goods_id,$goods_count,$attr){
        //將屬性資訊做一個從小到大的排序  目的就是為了後期庫存量的檢查
        sort($attr);
        //將屬性資訊裝換為字串格式
        $goods_attr_ids=$attr ? implode(',',$attr) : '';
        //實現庫存量的檢查
        $res=$this->checkGoodsNumber($goods_id,$goods_count,$goods_attr_ids);
        if(!$res){
            $this->error='庫存不足';
            return false;
        }
        //獲取使用者的id
        $user_id=session('user_id');
        if($user_id){
            //說明使用者已經登入,接下來的操作去操作資料表
            //根據當前要寫入的資料資訊 判斷資料庫是否已存在,如果存在直接更新對應的數量 否則直接寫入即可
            $map=array(
                'user_id'=>$user_id,
                'goods_id'=>$goods_id,
                'goods_attr_ids'=>$goods_attr_ids,
            );
            $info=$this->where($map)->find();
            if($info){
                //說明資料庫已經存在
                $this->where($map)->setField("goods_count",$goods_count+$info['goods_count']);
            }else{
                //說明目前資料不存在 直接寫入資料庫
                $map['goods_count']=$goods_count;
                $this->add($map);
            }
        }else{
            //處理沒有登入時新增購物車
            //說明使用者沒有登入 對應操作cookie中的資料
            //cookie中使用cart名稱 陣列轉為字串使用序列化
            $cart=unserialize(cookie('cart'));
            //先判斷目前新增的商品是否存在
            //首先拼接出對應的key下標
            $key=$goods_id.'-'.$goods_attr_ids;
            if(array_key_exists($key,$cart)){
                //說明目前新增的商品資訊已經存在
                $cart[$key]+=$goods_count;
            }else{
                //說明目前新增的商品不存在
                $cart[$key]=$goods_count;
            }
            //處理完之後需將最新資料寫入cookie
            cookie('cart',serialize($cart));

        }
        return true;
    }

庫存檢查:


//檢查庫存
    public function checkGoodsNumber($goods_id,$goods_count,$goods_attr_ids){
        //1.檢查總的庫存量
        $goods=D('Admin/Goods')->where("id=$goods_id")->find();
        if($goods['goods_number']<$goods_count){
            //庫存不足
            return false;
        }
        //2.根據單選屬性 檢查對應組合的庫存量
        if($goods_attr_ids){
            $where="goods_id=$goods_id and goods_attr_ids='$goods_attr_ids'";
            $number=M("GoodsNumber")->where($where)->find();
            if(!$number || $number['goods_number']<$goods_count){
                //庫存不足
                return false;
            }
        }
        return true;
    }
登入後購物車資料轉移

該方法在使用者使用者登入成功之後觸發,將cookie中的資料轉移到購物車資料表中D('Cart')->cookie_db;

這裡就不敘述了,直接上程式碼:


//具體實現cookie中的購物車資訊轉移到資料庫中
    public function cookie_db(){
        //獲取cookie中購物車的資料
        $cart=unserialize(cookie('cart'));
        //獲取當前使用者的id標識
        $user_id=session('user_id');
        if(!$user_id){
            return false;
        }
        foreach ($cart as $key=>$value){
            //先將目前下標對應的商品id和屬性id組合拆分出來
            $tmp=explode('-',$key);
            /*$goods_id=$tmp[0];
            $goods_attr_ids=$tmp[1];
            $goods_count=$value;*/
            $map=array(
                'user_id'=>$user_id,
                'goods_id'=>$tmp[0],
                'goods_attr_ids'=>$tmp[1],
            );
            $info=$this->where($map)->find();
            if($info){
                //說明cookie存在相同商品資訊 直接更新數量
                $this->where($map)->setField("goods_count",$value+$info['goods_count']);
            }else{
                //說明當前cookie中不存在該類商品資訊
                $map['goods_count']=$value;
                $this->add($map);
            }
        }
        //將目前cookie中的資料清空
        cookie('cart',null);
    }

購物車列表顯示

  1. 在購物車控制器增加方法獲取資料(getList)並載入對應的購物車列表頁;

  2. 在模型中實現方法獲取購物車的資料;

    
    //獲取購物車中 商品的具體資訊
        public function getList(){
            //1.獲取當前購物車中對應的資訊
            $user_id=session('user_id');
            if($user_id){
                //標識使用者已經登入 可以從資料庫獲取資料
                $data=$this->where('user_id='.$user_id)->select();
            }else{
                //沒有登入 直接從cookie中獲取資料
                $cart=unserialize(cookie('cart'));
                //將cookie中的資料裝換為資料庫中的格式
                foreach ($cart as $key=>$value){
                    $tmp=explode('-',$key);
                    $data[]=array(
                        'goods_id'=>$tmp[0],
                        'goods_attr_ids'=>$tmp[1],
                        'goods_count'=>$value,
                    );
                }
            }
            //2.根據購物車中商品id獲取商品基本資訊
            $goodsModel=D("Goods");
            foreach ($data as $key=>$value){
                //獲取具體的商品資訊
                $goods=$goodsModel->where('id='.$value['goods_id'])->find();
                //根據商品是否處於促銷狀態設定價格
                if($goods['cx_price']>0 && $goods['start']<time() && $goods['end'>time()]){
                    //處於促銷 將shop_price設定為cx_price
                    $goods['shop_price']=$goods['cx_price'];
                }
                $data[$key]['goods']=$goods;
                //3.根據商品對應的屬性組合 獲取屬性名和屬性值
                if($value['goods_attr_ids']){
                    //獲取商品的屬性資訊
                    $attr=D('GoodsAttr')->alias('a')->field("a.attr_values,b.attr_name")->join("left join jx_attribute b on a.attr_id=b.id")->where("a.id in ({$value['goods_attr_ids']})")->select();
                    $data[$key]['attr']=$attr;
                }
            }
            return $data;
        }
  3. 然後修改購物車列表模板,進行資料的顯示;

  4. 在控制器中呼叫方法運算總金額(getTotal),並修改模板顯示總金額;

    
    //實現購物車中總金額計算
        public function getTotal($data){
            //初始商品及總數都為0
            $count=$price=0;
            foreach ($data as $key=>$value){
                $count+=$value['goods_count'];
                $price+=$value['goods_count']*$value['goods']['shop_price'];
            }
            return array('count'=>$count,'price'=>$price);
        }

購物車中的商品刪除

  1. 在購物車列表給‘刪除’增加連結地址;

    <a href="{:U('dels','goods_id='.$vo['goods_id'].'&goods_attr_ids='.$vo['goods_attr_ids'])}">刪除</a>
  2. 在控制器中定義方法實現刪除功能,get到goods_id,goods_attr_ids;

  3. 在模型中實現刪除的方法;

    
    //具體實現購物車中商品刪除功能
        public function dels($goods_id,$goods_attr_ids){
            $goods_attr_ids=$goods_attr_ids ? $goods_attr_ids : '';
            $user_id=session('user_id');
            if($user_id){
                $where="goods_id=$goods_id and user_id=$user_id and goods_attr_ids='$goods_attr_ids'";
                $this->where($where)->delete();
            }else{
                $cart=unserialize(cookie("cart"));
                //手動拼接當前商品對應的key資訊
                $key=$goods_id.'-'.$goods_attr_ids;
                unset($cart[$key]);
                //將最新的資料再次寫入cookie
                cookie('cart',serialize($cart));
            }
        }

ajax修改購物車列表商品數量

  1. 修改模板給增加跟減少設定屬性;

    用於標識出當前修改的具體是哪一個商品數量的資訊:

    <a href="javascript:;" data-goods-id="{$vo.goods_id}" data-goods-attr-ids="{$vo.goods_attr_ids}" class="reduce_num"></a>
  2. 對增加跟減少繫結點選事件觸發ajax;

    
    <script type="text/javascript">
    //針對減少繫結點選事件
    $(".reduce_num").click(function () {
    var goods_id=$(this).attr("data-goods-id");
    var goods_attr_ids=$(this).attr("data-goods-attr-ids");
    var goods_count=$(this).next().val();
    if(goods_count>1){
        updateCount(goods_id,goods_attr_ids,goods_count-1);
    }
        });
        //針對增加繫結點選事件
        $(".add_num").click(function () {
            var goods_id=$(this).attr("data-goods-id");
            var goods_attr_ids=$(this).attr("data-goods-attr-ids");
            var goods_count=$(this).prev().val();
            //需要將目前獲取到的數字裝換為整形數字
    goods_count=parseInt(goods_count)+1;
    updateCount(goods_id,goods_attr_ids,goods_count);
        });
        //實現具體傳送ajax
    function  updateCount(goods_id,goods_attr_ids,goods_count){
        $.ajax({
    url:"{:U('updateCount')}",
    data:{goods_id:goods_id,goods_attr_ids:goods_attr_ids,goods_count:goods_count},
    type:'post',
    success:function () {
                }
    });
    }
    </script>
  3. 在購物車控制器中增加方法接受請求;

    
    //更新購物車中商品數量
        public function updateCount(){
            $goods_id=I("post.goods_id");
            $goods_attr_ids=I("post.goods_attr_ids");
            $goods_count=I("post.goods_count");
            D("Cart")->updateCount($goods_id,$goods_attr_ids,$goods_count);
        }