reids +laravel5 实现商品排序

16 篇文章 0 订阅
4 篇文章 0 订阅
<?php
namespace App\Http\Controllers;
use Mockery\Exception;
use \Redis;
class GoodsController extends Controller
{

    protected $cate;              // 分类
    protected $redis;             // redis实例
    protected $goodsCategoryPrefix = 'goods_category_';
    protected $goodsListInfoKey = 'goods_list_info';
    protected $goodsCategoryExpireTime = 10; // 分钟

    public function __construct()
    {
        $redis = new Redis;
        $redis->connect('127.0.0.1');
        $redis->select(6);
        $this->redis = $redis;
        $this->init();

        $this->setGoodsList();

    }

    /**
     *  初始化
     */
    public function init()
    {
        $this->cate = $cate = intval(request('cate', 1));
    }

    /**
     *  商品数据写入redis (维护数据)
     */
    public function setGoodsList()
    {
        $cate = $this->cate;
        $goods = [];
        $goods[] = ['id' => 1, 'name' => 'asd1', 'price' => 10, 'sales' => 5, 'weight' => 10];
        $goods[] = ['id' => 2, 'name' => 'asd2', 'price' => 20, 'sales' => 6, 'weight' => 9];
        $goods[] = ['id' => 3, 'name' => 'asd3', 'price' => 30, 'sales' => 7, 'weight' => 5];
        $goods[] = ['id' => 4, 'name' => 'asd4', 'price' => 40, 'sales' => 8, 'weight' => 7];
        $goods[] = ['id' => 5, 'name' => 'asd5', 'price' => 50, 'sales' => 1, 'weight' => 1];
        $goods[] = ['id' => 6, 'name' => 'asd6', 'price' => 50, 'sales' => 5, 'weight' => 5];
        $goods[] = ['id' => 7, 'name' => 'asd7', 'price' => 70, 'sales' => 2, 'weight' => 2];

        $currentTime = time();
        // 初始化导入商品
        if (!empty($cate) && $this->redis->hLen($this->goodsListInfoKey) < 1) {
            //dd($this->redis->zRange($goodsCateKey ,0 ,-1,true));
            //if( $this->redis->ttl($goodsCateKey) < 0){
            $goodsHsahData = [];
            foreach ($goods as $val) {
                $goodsCateKey = $this->goodsCategoryPrefix . 'price_' . $cate;
                $this->redis->zAdd($goodsCateKey, $val['price'], $val['id']);
                $goodsCateKey = $this->goodsCategoryPrefix . 'sales_' . $cate;
                $this->redis->zAdd($goodsCateKey, $val['sales'], $val['id']);
                $goodsCateKey = $this->goodsCategoryPrefix . 'weight_' . $cate;
                $this->redis->zAdd($goodsCateKey, $val['weight'], $val['id']);
                $goodsHsahData[$val['id']] = serialize($val);  // 将所有商品信息写入哈希表
            }
            $this->redis->hMSet($this->goodsListInfoKey, $goodsHsahData);
            //$this->redis->expireAt($goodsCateKey, $currentTime + $this->goodsCategoryExpireTime * 60);
            //}
        }
    }

    /**
     * 排序
     * @return array
     */
    public function sort()
    {
        $sortField = request('field', 'weight');  // 排序字段
        $sortType = request('order', 'asc');      // 升降序 [ 'asc' , 'desc']
        $scoreMin = request('min');               // 分数区间最小值 默认 -inf
        $scoreMax = request('max');               // 分数区间最大值 默认 +inf
        $page     = intval(request('page', 1));   // 分页参数
        $cate     = $this->cate;                  // 商品分类


        if (!in_array($sortField, ['price', 'sales', 'weight']) ||
            !in_array($sortType, ['asc', 'desc'])
        ) {
            throw new Exception('排序参数错误~~~~~~');
        }

        // 分页偏移
        list($start, $end) = $this->setPage($page, 3);
        // 分数区间
        list($fieldScoreMin, $fieldScoreMax, $isNeedScore) = $this->setScore($scoreMin, $scoreMax);

        // 需要排序的有序集合
        $sortCateKey = $this->goodsCategoryPrefix . $sortField . '_' . $cate;

        if ($sortType == 'asc' && !$isNeedScore) {
            // 无区间排序(升序)
            $goodsIds = $this->redis->zRange($sortCateKey, $start, $end);
        } else if ($sortType == 'desc' && !$isNeedScore) {
            // 无区间排序(降序序)
            $goodsIds = $this->redis->zRevRange($sortCateKey, $start, $end);
        } else if ($sortType == 'asc' && $isNeedScore) {
            // 分区排序(升序)
            $goodsIds = $this->redis->zRangeByScore($sortCateKey, $fieldScoreMin, $fieldScoreMax, 
            ['limit' => [$start ,$end]]);
        } else {
            // 分区排序(降序)
            $goodsIds = $this->redis->zRevRangeByScore($sortCateKey, $fieldScoreMax, $fieldScoreMin,
             ['limit' => [$start ,$end],'withscores' => false]);
        }

        // 从商品列表里面找出对应的商品
        $lists = $this->redis->hMGet($this->goodsListInfoKey, $goodsIds);

        if(false === $lists){
            dd('没找到商品数据');
            return [ 'status' => 0 , 'msg' => '没找到商品数据' ];
        }
        foreach ($lists as &$list) {
            $list = json_encode(unserialize($list));
        }
        dd($lists);
    }


    /**
     * 设置分页
     * @param int $page
     * @param int $offset
     * @return array
     */
    public function setPage(int $page = 1, $offset = 10)
    {
        if ($page < 1) $page = 1;
        $start = ($page - 1) * $offset;
        $end = $page * $offset;
        return [$start, $end];
    }

    /**
     * 设置区间
     * @param string $min
     * @param string $max
     * @return array
     */
    public function setScore($min = '-inf', $max = '+inf')
    {
        $numericMin = $min + 0;  // 支持小数
        $numericMax = $max + 0;

        $isNeedScore = true;
        if ((is_null($min) && is_null($max))) {
            $isNeedScore = false;
        } else if (!is_null($min) && !is_null($max)) {

        } else {
            $min = is_null($min) ? '-inf' : $numericMin;
            $max = is_null($max) ? '+inf' : $numericMax;
        }

        return [$min, $max, $isNeedScore];
    }


}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值