完善购物车系统

目录:

  1. 完善加入购物车的提示页
  2. 完善购物车的删除
  3. 细节说明

之前有写了一个购物车,将会员和游客,分开.会员加车存数据库,游客加车存cookie.但是这个系统,加入购物车就会跳转至购物车页面.但是在京东等电商当中,我发现他们并不是这样处理的

图片来自京东

京东会先跳往一个加入购物车成功的一个页面.这样做有什么好处呢

  • 可以诱导用户继续购物
  • 可以让cookie写入成功(这个在后面会有详细说明)
  • 可以不用将某件商品加入购物车,而直接进入购物车(这算是个bug的修复)

首先我们需要明白,做这样的购物车优化,我们需要些什么.

  • 首先我们需要一个前端页面代码,这个不是今天的重点,我就不说了

我们直接来看看流程图


购物车优化.png

我们按照这个思路,写了一个加入购物车提示页方法

    /**
     * 提示加车成功页面
     */
    public function actionCarttips()
    {
        //接收前台数据
        $data = Yii::$app->request->get();
        //判断用户是否登陆
        if (Yii::$app->user->isGuest) {
            //如果没有登陆,调用未登陆加车方法
            if (!$this->guestAddCart($data)) {
                echo '数据出错,稍后再试游客';
                exit;
            }
        } else {
            //如果登陆,调用登陆加车方法
            if (!$this->memberAddCart($data)) {
                echo '数据出错,稍后再试';
                exit;
            }
        }
        //渲染加车提示页面,传入id,继续购物使用
        return $this->render('CartTips', ['goods_id' => $data['goods_id']]);
    }

在这段代码中,我在这个控制器里之前就已经封装好了,游客和会员两个不同的加入购物车方法.
由于商品详情页,我使用的是页面静态化,所有只能使用get传值来避免csrf验证
get接收到值过后,传给相应的方法,完成加车,渲染加车提示页面.
这里有个小细节,我们传递了一个goods_id到前端页面,这里是为了让用户点击继续购物的时候能够直接跳回之前的那个商品页面.让用户体验更完善.


下面我们来看看购物车里商品的删除,一个购物车,必须得有删除功能,我们不能规定用户加入购物车后就不能删除,也许是用户手滑或则别的什么原因,购物车里必须有删除.

这里我们选择的是异步请求删除
之所以要选择异步是因为,异步删除不刷新页面感觉比较高级.还有就是异步请求,只会传递数据,并不会重新加载静态资源.这样反应也会比较快

下面我们来看看删除购物车的流程


购物车删除.png

我们先来看前端jquery代码

<script type="text/javascript" src="<?= Yii::$app->params['jquery'] ?>"></script>
<script type="text/javascript" src="/statics/plug/layer/layer/layer.js"></script>
<script type="text/javascript" src="/statics/js/cart1.js"></script>
<script type="text/javascript">
    $(function () {
        //使用事件委派,委派到删除的a标签上.a标签有两个属性,一个是class="del",一个是goods_id="对应的商品id"
        $("#cart_content").on('click', ".del", function (event) {
            //获取到id
            var goods_id = $(event.target).attr('goods_id');
            //通过寻找父级对象.找到点击删除的那一行tr
            var dom = $(event.target).parents('.num_tr');
            if (confirm('您真的要删除这个商品吗')) {
                //将id发送到后台接口,获取json结果
                $.getJSON(
                    '<?=\yii\helpers\Url::to(['goods/delcart'])?>',
                    {'goods_id': goods_id},
                    function (data) {
                        if (data.status) {
                            //成功
                            layer.msg(data.message, {icon: 1});
                            //删除dom节点
                            dom.remove();
                           //重新计算总价
                            var price = 0;
                            if ($(".onePrice") !== undefined) {
                                $('.onePrice').each(function (i, v) {
                                    price += Number($(v).text());
                                });
                            }
                            $("#total").text(price);
                        } else {
                            //弹出小标签提示
                            layer.msg(data.message, {icon: 2});
                        }
                    }
                )
            }
        })
    })
</script>

前段jq代码,使用了两个小技术.一个是事件委派,一个是ajax异步请求技术.这里就不细讲了.我们重点来看看后台的接口方法

    /**
     * 删除购物车中的数据接口
     */
    public function actionDelcart()
    {
        $goods_id = Yii::$app->request->get('goods_id');
        if (Yii::$app->user->isGuest) {
            //游客
            //获取cookie
            $cookieobj = Yii::$app->request->cookies;
            $cookieValue = $cookieobj->getValue('cart_cookie');
            if (empty($cookieValue)) {
                echo json_encode(['status' => 0, 'message' => '购物车中没有这个商品']);
                exit;
            }
            //反序列化cookie中的数据
            $cartArr = unserialize($cookieValue);
            foreach ($cartArr as $key => $value) {
                if ($key == $goods_id) {
                    unset($key);
                }
            }
            //序列化
            $serArr = serialize($cartArr);
            //将cookie写入
            Yii::$app->response->cookies->add(new Cookie([
                'name' => 'cart_cookie',
                'value' => $serArr
            ]));
            echo json_encode(['status' => 1, 'message' => '删除成功']);
        }
        else{
            //会员
            //查出数据库中这个商品的对象
            $cartModel=Cart::findOne(['goods_id'=>$goods_id,'user_id'=>Yii::$app->user->identity->getId(),'status'=>2]);
            if (empty($cartModel)) {
                echo json_encode(['status' => 0, 'message' => '购物车中没有这个商品']);
                exit;
            }
            //修改这条商品的状态
            $cartModel->status=0;
            $cartModel->save();
            echo json_encode(['status' => 1, 'message' => '删除成功']);
        }
    }

这里首先将游客和会员分开,使用Yii::$app->user->isGuset来判断

  • 游客的话,要复杂一点,我们将cookie里的数据取出,然后找到相应的goods_id对应的那条数据,将它删除,随后,又将剩下的数据再序列化后,再写入cookie.返回json化的执行结果
  • 会员我们是选择查出购物车表中的含有当前用户和含有goods_id的一条数据对象
    将这一对象的状态改为0,这样完成的删除,同样的,返回一条json化的执行结果

之前有提到要在购物车中加上提示页面,对写入cookie更友好.

我们都知道,cookie是存储在浏览器中的数据.当我们的代码执行到写入一条cookie时,并没有真正的写入,原因是我们必须在response,也就是渲染页面时候才能写入到cookie,在之前的版本中.我发现,当我渲染页面,在cookie中取值,并没有刚加入的cookie数据.

当时我的解决方案就是,在渲染页面中把get到的值,合并到之前的cookie中,来解决cookie写入慢半拍的问题,可是这一解决方案,始终感觉不够优雅,数据来源复杂化了.

所有采用中间加一页的方法的话,就在渲染提示页的时候就成功加入cookie,当用户这是点击购物车时候,我们直接到cookie中取值,就可与取到完整的数据

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 173,179评论 25 708
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,891评论 18 139
  • 全文链接 第一章 创建一个blog应用第二章 使用高级特性来增强你的blog第三章 扩展你的blog应用第四章上 ...
    夜夜月阅读 10,098评论 27 36
  • 收拾起行囊 面对陌生的远方 点一支烟 看自己的双脚和足迹 为那荒唐的图案而懊悔 为那诚恳和朴实而羞愧 朋友说 那是...
    一言一语一行阅读 228评论 0 0
  • 输出信息含义 执行netstat后,其输出结果为 Active Internet connections (w/o...
    bailongxian阅读 1,267评论 0 2