ThinkPHP5+Redis實現購物車

本篇文章是經過ThinkPHP5和Redis實現購物車,功能包括:購物車列表、添加購物車、獲取部分商品、獲取部分商品總數量、獲取所有商品總數量、商品減1、修改商品數量、刪除商品、清空購物車,這些功能基本上可以知足購物車的需求,代碼寫的不夠嚴謹,但大體邏輯就是這樣。php

前提:安裝PHP運行環境,安裝Redis,PHP安裝Redis擴展,須要同時知足以上三個條件才能使用Redis。html

參考文章:前端

1、先看一個運行截圖(主要實現功能,頁面沒有優化)redis

 2、附上代碼json

一、前端後端

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8">
</head>
<body>
<h3>個人購物車</h3>
<form action="/index/index/index" method="post">
    
    <input type="text" name="ids">
    <input type="submit" value="獲取部分商品信息">
    <span style="color: gray; font-size: 14px;">用英文逗號隔開</span>
</form>
所選商品數量:{$totalnum}
<br><br>

<form action="/index/index/emptyCart">
    <input type="submit" value="清空購物車">
</form>
<br>

<table border="1">
    <tr align="center">
        <td style="width: 100px">商品ID</td>
        <td style="width: 100px">商品屬性ID</td>
        <td style="width: 100px">商品名</td>
        <td style="width: 100px">商品屬性名稱</td>
        <td style="width: 100px">數量</td>
        <td style="width: 100px">單價</td>
        <td style="width: 100px">運費</td>
        <td style="width: 100px">總價</td>
        <td style="width: 100px">操做</td>
    </tr>
    {volist name="list" id="vo"}
    <tr align="center">
        <td style="width: 100px">{$vo.goods_id}</td>
        <td style="width: 100px">{$vo.attr_id}</td>
        <td style="width: 100px">{$vo.goods_name}</td>
        <td style="width: 100px">{$vo.attr_name}</td>
        <td style="width: 100px">{$vo.goods_number}</td>
        <td style="width: 100px">{$vo.price}</td>
        <td style="width: 100px">{$vo.freight}</td>
        <td style="width: 100px">{$vo.subtotal}</td>
        <td style="width: 100px"><a href="/index/index/del.html?id={$vo.goods_id}">刪除</a></td>
    </tr>
    {/volist}
</table>

<br/>
<hr/>


<h3>添加購物車</h3>

<form action="/index/index/addbasket" method="post">
    
    商品ID:<input type="text" name="goods_id" value="111">
    商品屬性ID:<input type="text" name="attr_id" value="222">
    商品名:<input type="text" name="goods_name" value="U盤">
    商品屬性名稱:<input type="text" name="attr_name" value="數碼類">
    <br/><br/>&nbsp; &nbsp;量:<input type="text" name="number" value="1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;價:<input type="text" name="price" value="12">&nbsp; 費:<input type="text" name="freight" value="10">

    <input type="submit" value="添加購物車">
</form>

<br/>
<hr/>

<h3>某一商品減一</h3>
<form action="/index/index/reduce" method="post">
    商品ID:<input type="text" name="id"> 
    商品屬性ID:<input type="text" name="attr_id"> 
    減去數量:<input type="text" name="number"> 
    <input type="submit" value="減一">
</form>
<br/>
<hr/>

<h3>編輯商品</h3>
<form action="/index/index/edit" method="post">
    商品ID:<input type="text" name="id"> 
    商品屬性ID:<input type="text" name="attr_id"> 
    修改數量:<input type="text" name="number"> 
    <input type="submit" value="修改">
</form>
<br/>
<hr/>

</body>
</html>

二、後端代碼數組

<?php
namespace app\index\controller;
use think\Controller;
use think\cache\driver\Redis;

class Index extends Controller
{

    private $expire = 43200;    //redis緩存過時時間  12h
    private $redis = null;
    private $cachekey = null;    //緩存變量名
    private $basket = [];        //私有數組,存放商品信息

    private $user_id = '110';
    
    /**
     * 購物車初始化,傳入用戶id
     */
    public function __construct()
    {
        parent::__construct();

        $this->redis = new \Redis();        // 實例化
        $this->redis->connect('127.0.0.1','6379');
        $this->redis->auth('zxf123456');

        $this->cachekey = 'user'.$this->user_id.'.cart';    //redis緩存鍵名拼接用戶id與字符串爲對象用戶購物車緩存鍵名  user110.cart
        $this->basket = json_decode($this->redis->get($this->cachekey),true);    //獲取對象用戶的redis購物車商品緩存信息並解碼爲數組
    }

    /**
     * 獲取全部商品信息
     */
    public function index()
    {
        $ids = input('post.ids');
        // 若是獲取部分商品信息(搜索進來)
        if (!empty($ids)) {

            // 獲取部分商品信息
            $list = $this->getPartGoods($ids);

            // 獲取部分商品數量
            $totalnum = $this->getPartGoodsNum($ids);

        }else{
            // 默認所有列表
            $list = $this->basket;
            // 獲取全部商品數量
            $totalnum = $this->getAllDoodsNum();
        }
        $this->assign(['list'=>$list,'totalnum'=>$totalnum]);
        return $this->fetch();
    }

    /**
     * 添加商品到購物車
     * @param 商品id 商品屬性id 商品名稱 數量 價格
     */
    public function addbasket()
    {

        $data = request()->param();
        // 判斷對象是否已經存在redis購物車緩存中
        if ($this->isExist($data['goods_id'],$data['attr_id'])) {

            // 存在緩存中,增長該商品數量
            return $this->add($data['goods_id'],$data['attr_id'],$data['number']);
        }

        // 對象商品不在redis緩存中時
        $tmp = [];
        $tmp['goods_id'] = intval($data['goods_id']);    //商品id
        $tmp['attr_id'] = intval($data['attr_id']);    //商品屬性id
        $tmp['goods_name'] = $data['goods_name'];        //商品名
        $tmp['attr_name'] = $data['attr_name'];            //商品屬性名稱
        $tmp['goods_number'] = intval($data['number']);            //商品數量,新增的商品默認加入數量爲1
        $tmp['price'] = intval($data['price']);            //商品價格
        $tmp['freight'] = intval($data['freight']);        //運費

        $tmp['subtotal'] = $tmp['goods_number'] * $tmp['price'] + $tmp['freight'];    //商品總價

        $this->basket[] = $tmp;        // 把新的商品信息追加到以前的商品緩存數組中,每件屬性商品對應一個索引鍵值

        
        // 把新的購物車信息編碼爲json字符串,並從新存入到redis購物車緩存中
        $this->redis->setex($this->cachekey,$this->expire,json_encode($this->basket));

        // return 1;
        echo "<script>alert('添加成功');window.location.replace(document.referrer);;</script>";
    }

    /**
     * 判斷商品是否已經存在
     * @param 商品id 商品屬性id
     */
    public function isExist($id,$attr_id)
    {
        $isExist = false;
        // 當對象用戶redis購物車商品緩存不爲空時
        if (!empty($this->basket)) {

            foreach ($this->basket as $key => $value) {
                // 判斷當前商品是否存在
                if ($value['goods_id'] == $id && $value['attr_id'] == $attr_id) {
                    $isExist = true;
                    break;
                }
            }
        }
        return $isExist;
    }

    /**
     * 添加商品
     */
    public function add($id,$attr_id,$number)
    {

        $goods_number = 0;    //加入不成功時默認添加數量爲0
        // 商品id不爲空而且商品在redis購物車商品緩存中
        if (!empty($id) && $this->isExist($id,$attr_id)) {

            $cache_detail = $this->basket;        //獲取用戶購物車全部商品
            foreach ($cache_detail as $key => $value) {

                if ($value['goods_id'] == $id && $value['attr_id'] == $attr_id) {

                    // 只修改商品數量和總價
                    $value['goods_number'] = $value['goods_number'] + $number;    //增長購物車商品數量
                    $value['subtotal'] = $value['goods_number'] * $value['price'] + $value['freight'];    //從新計算總價  數量*單價+運費
 

                    $this->basket[$key] = $value;    //把該商品從新放到redis緩存中
                    $this->redis->setex($this->cachekey,$this->expire,json_encode($this->basket));

                    $goods_number = $value['goods_number'];
                    break;

                }
            }
        }
        return $goods_number;    //返回商品數量
    }

    /**
     * 獲取部分商品
     */
    public function getPartGoods($ids)
    {
        // 字符串轉數組
        $ids = explode(',', $ids);
        $goods = [];
        // 循環ids數組,循環redis緩存數組,當商品id一致時,取出來存到goods數組中
        foreach ($ids as $v) {
            foreach ($this->basket as $key => $value) {
                if ($value['goods_id'] == $v) {

                    $goods[] = $value;
                }
            }
        }
        return $goods;
    }

    /**
     * 獲取部分商品總數
     */
    public function getPartGoodsNum($ids)
    {
        // 字符串轉數組
        $ids = explode(',', $ids);
        $number = 0;    //默認爲0
        foreach ($ids as $v) {

            foreach ($this->basket as $key => $value) {

                // 取出redis緩存中有該id的商品數量
                if ($value['goods_id'] == $v) {
                    $number += $value['goods_number'];
                }
            }
        }
        return $number;
    }

    /**
     * 獲取所有商品數量
     */
    public function getAllDoodsNum()
    {
        $number = 0;
        if (!empty($this->basket)) {
            foreach ($this->basket as $key => $value) {
                $number += $value['goods_number'];
            }
        }
        return $number;
    }

    /**
     * 某一商品數量減一
     */
    public function reduce()
    {
        $data = request()->param();
        $goods_number = 0;    //默認減0

        // 若是接收的數據不爲空,而且該商品信息存在
        if (!empty($data) && $this->isExist($data['id'],$data['attr_id'])) {

            // 獲取redis緩存裏的數據
            $cache_detail = $this->basket;

            // 循環判斷,從緩存商品列表中找到該條商品,數量並減一
            foreach ($cache_detail as $key => $value) {
                if ($value['goods_id'] == $data['id'] && $value['attr_id'] == $data['attr_id']) {

                    // 先判斷當前商品的數量是否大於要刪除的數量
                    if ($value['goods_number'] < $data['number']) {

                        echo "<script>alert('商品數量不足');window.history.back();</script>";
                        break;
                    }
                    // 若是當前商品數量爲1,則刪除
                    if ($value['goods_number'] <= 1) {

                        // 循環判斷找出該商品,並刪除
                        foreach ($this->basket as $key => $value) {
                            if ($value['goods_id'] == $data['id']) {
                                // 從數組中移除當前商品
                                array_splice($this->basket, $key, 1);
                            }
                        }
                        // 從新存入緩存
                        $this->redis->setex($this->cachekey,$this->expire,json_encode($this->basket));
                        $goods_number = 0;

                    }else{

                        // 數量減
                        $value['goods_number'] = $value['goods_number'] - $data['number'];
                        $goods_number = $value['goods_number'];
                        // 計算總價
                        $value['subtotal'] = $value['goods_number'] * $value['price'];
                        
                        // 把新的數據追加到$this->basket
                        $this->basket[$key] = $value;

                        // 從新存入緩存
                        $this->redis->setex($this->cachekey,$this->expire,json_encode($this->basket));
                    }
                }
            }
        }
        // return $goods_number;
        echo "該商品當前數量爲".$goods_number;
    }

    /**
     * 刪除商品
     */
    public function del()
    {
        $id = input('id');
        // 循環判斷,並刪除
        foreach ($this->basket as $key => $value) {
            if ($value['goods_id'] == $id) {
                // 從數組中移除當前商品
                array_splice($this->basket, $key, 1);
            }
        }
        $this->redis->setex($this->cachekey,$this->expire,json_encode($this->basket));
        // return true;
        echo "<script>alert('刪除成功');window.location.replace(document.referrer);;</script>";
    }

    /**
     * 編輯商品
     */
    public function edit()
    {
        $data = input('post.');
        if (!empty($data) && $this->isExist($data['id'],$data['attr_id']) && $data['number'] > 0) {

            // 取出緩存中的數據
            $cache_detail = $this->basket;

            // 循環判斷,取出當前商品信息,並修改
            foreach ($cache_detail as $key => $value) {

                if ($value['goods_id'] == $data['id'] & $value['attr_id'] == $data['attr_id']) {

                    // 商品數量
                    $value['goods_number'] = intval($data['number']);
                    // 商品總價 數量*單價+運費
                    $value['subtotal'] = $value['goods_number'] * $value['price'] + $value['freight'];
                    // 賦值
                    $this->basket[$key] = $value;

                    // 從新存儲到緩存
                    $this->redis->setex($this->cachekey,$this->expire,json_encode($this->basket));
                    echo "該商品當前數量爲".$value['goods_number'];
                }
            }
        }
    }

    /**
     * 清空購物車
     */
    public function emptyCart()
    {
        $this->redis->rm($this->cachekey);
        echo "<script>alert('購物車清空成功');window.location.replace(document.referrer);;</script>";
    }

}

有一點須要注意:「use think\cache\driver\Redis;」把redis引進來,這個Redis文件是TP5自帶的,不用下載就能夠直接用。代碼裏有註釋,其餘的就再也不說明了,其餘文件也沒有什麼需求配置的緩存

 

3、常見錯誤app

列一下我在使用過程當中遇到的問題函數

  1. 在「清空購物車」這個功能裏,有一句「 $this->redis->rm($this->cachekey);」,執行這句的時候會報錯,"Function Redis::delete() is deprecated",意思是delete()這個函數已經被棄用了,能夠查找到Redis文件裏rm()這個函數,裏面用到了delete()這個函數,只須要把delete()改爲del就能夠了,由於php-redis 5 已經把這個函數棄用了

其餘棄用函數

相關文章
相關標籤/搜索