投票代码PHP实例

思路讲解:

* 投票有效期为  86400*7
* 一个赞的分值为 86400 / 200  = 432
*
* hash 存储文章的内容, key为文章的id
* zset key为文章id,score为文章发布时间,存时间戳
* zset key为文章id,score为文章的分值
* set 记录投票用户与对应文章

完整代码:


class Vote
{
    private $redis;
    const SCORE = 432;      // 此方式可以在输出文章详情的给出,这里没有计算
    const VOTE_EXPIRE_TIME = 86400 * 7;
    public function __construct()
    {
        $this->redis = new \Redis();
        $this->redis->connect('172.17.0.3','6379','5');
        $this->redis->select(7);
    }

    // 发布文章
    public function postArticle($content) {
        $author_id = $content['poster'];         // 作者id
        // 这里使用了incr自增的操作
        $article_id = $this->redis->incr('article:');   // 文章id
        // 添加文章
        $article_key = 'article:'.$article_id;
        $this->redis->hMSet($article_key, $content);
        // 将文章添加到发布时间有序集合中
        $this->redis->zAdd("time:",time(),$article_key);
        // 将文章添加到分数有序集合中
        $this->redis->zAdd("score:",1, $article_key);
        // 创建投票集合,并将作者添加进去
        $this->redis->sAdd("vote:".$article_id, $author_id);
        // 设置投票集合的有效期
        $this->redis->expire("vote:".$article_id, self::VOTE_EXPIRE_TIME);
        return $article_id;
    }

    // 给文章投票
    // $vote_id     投票用户id
    // $article_id  文章id
    public function voteArticle($vote_id, $article_id) {
        $article_key = 'article:'.$article_id;
        $vote_key = 'vote:'.$article_id;
        // 判断文章是否存在
        if (!$this->redis->exists($article_key)) {
            echo '未找到文章信息!';
            exit();
        }
        // 判断是否过投票期
        $cutOff = time() - self::VOTE_EXPIRE_TIME;
        $post_time = $this->redis->zScore("time:",$article_key);
        if ($post_time < $cutOff) {
            echo '投票时间已过!';
            exit();
        }
        // 判断是否已经投过了
        /*if ($this->redis->SISMEMBER($vote_key, $vote_id)) {

        }*/
        // 直接插入,如果插入失败则代表已经存在
        if ($this->redis->sAdd($vote_key,$vote_id)) {
            // 分数更新
            //$this->redis->zIncrBy("score:",$article_key,1);
            $this->redis->zIncrBy("score:",1, $article_key);
            // 文章更新
            $this->redis->hIncrBy($article_key,'votes',1);
            echo "投票成功";
        } else {
            echo '已投票!不能重复投票';
            exit();
        }
    }

    // 获取文章列表
    public function getArticle($page = 1, $size = 10, $order='score:') {
        $start = ($page - 1) * $size;
        $end = $start + $size - 1;
        $ids = $this->redis->zRevRange($order, $start, $end);
        foreach ($ids as $id) {
            $data = $this->redis->hGetAll($id);
            $data['article_id'] = $id;
            $articles[] = $data;
        }
        return $articles;
    }


    // 将文章加入到不同的分组中,或者从分组中移除
    public function addOrRemoveGroup($article_id, $group_id=[], $type = 'add') {
        $article_key = "article:".$article_id;
        $op = $type=='add' ? 'sAdd' : 'sRem';
        foreach ($group_id as $item) {
            $this->redis->$op("group:".$item, $article_key);
        }
        echo $op . '成功';
    }

    // 获取不同分组的文章
    public function getGroupArticle($orders="score:", $group_id) {
        $save_key = "new_group:".$orders . $group_id.":".session_id();
        if (!$this->redis->exists($save_key)) {
            $this->redis->zinterstore($save_key, ["group:".$group_id, $orders]);
        }
        $list = $this->getArticle(1,3, $save_key);
        $this->redis->del($save_key);
        return $list;
    }

}

// 测试部分

// 分组 1-redis 2-php 3-mysql
$vote = new Vote();
// 这里数据可以重复构造
$article_content = [
    'title' => 'mysql基础_2',
    'link' => 'http://www.baidu.com',
    'poster' => 'user:2',
    'time' => time(),
    'votes' => 1
];
//print_r($vote->postArticle($article_content));
// 投票
//echo $vote->voteArticle("user:3",2);
// 获取文章列表
/*$list = $vote->getArticle(1,3,"time:");
echo "<pre>";
print_r($list);
echo "<pre>";*/

// 文章分组
//$vote->addOrRemoveGroup(1,[1],'add');
//$vote->addOrRemoveGroup(3,[1],'add');

// 输出分组文章
$list = $vote->getGroupArticle("score:",1);
echo "<pre>";
print_r($list);
echo "<pre>";