<?php
namespace app\news\controller;
use app\login\model\News;
use think\facade\Cache;
/**
* Class ViewCount
* @package app\news\controller
* 文章浏览量类
*/
class ViewCount extends News
{
protected $redis = null;
protected $hash_prefix; //浏览数hash前缀
protected $field_prefix; //字段前缀
protected $id;
protected $date;
public function __construct()
{
$this->redis = Cache::store('redis');
$this->hash_prefix = 'news_view_counts_';
$this->field_prefix = 'news_';
$this->date = date('Y-m-d');
}
/**
* 设置文章浏览数
* 每天的文章浏览数存在redis hash,如news_view_counts_2020-07-13
* hash字段存储的是每个文章的浏览数,如news_1
* 获取hash字段的值,如存在+1,不存在设置1
* @param int $id 文章id
* @return bool
*
*/
public function viewCountIncrement($id)
{
if (empty($id)) {
return false;
}
$this->id = $id;
// 获取今日 Redis 哈希表名称,如:news_view_counts_2020-07-13
$hash = $this->getHashFromDateString();
// 字段名称,如:news_1
$field = $this->getHashField();
// 当前阅读数,如果存在就自增,否则就为 1
$count = $this->redis->hGet($hash, $field);
if ($count) {
$count++;
} else {
$count = 1;
}
// 数据写入 Redis,字段已存在会被更新
$this->redis->hSet($hash, $field, $count);
return true;
}
/**
* 获取文章浏览数
* 获取redis hash中的浏览数+数据库中的
* @param int $id 文章id
* @param int $view_count 数据库浏览数
* @return bool|int
*/
public function getViewCount($id, $view_count = 0)
{
if (empty($id)) {
return false;
}
$this->id = $id;
// 获取今日对应的哈希表名称
$hash = $this->getHashFromDateString();
// 字段名称,如:news_1
$field = $this->getHashField();
// 三元运算符,获取Redis中的文章浏览数数据,
$count = $this->redis->hGet($hash, $field) ?: 0;
// 如果存在的话,返回数据库中的阅读数 加上 Redis 中的阅读数
if ($count) {
return $view_count + $count;
} else {
return $view_count;
}
}
/**
* 异步更新文章浏览量
* hGetAll取出当天所有的数据,循环更新浏览数(数据库+redis)到mysql
* 每天凌晨1点执行前一天的浏览数入库
* @return bool|string
*/
public function syncNewsViewCounts()
{
// 获取昨日的哈希表名称,如:news_view_counts_2020-10-12
$yesterday = date('Y-m-d', strtotime('-1 day'));
$this->date = $yesterday;
$hash = $this->getHashFromDateString();
// 从 Redis 中获取所有哈希表里的数据
$counts = $this->redis->hGetAll($hash);
// 如果没有任何数据直接 return
if (count($counts) === 0) {
return false;
}
try {
// 遍历,并同步到数据库中
foreach ($counts as $news_id => $view_count) {
// 将 `news_1` 转换为 1
$news_id = str_replace($this->field_prefix, '', $news_id);
// 只有当文章存在时才更新到数据库中
if ($news = News::find($news_id)) {
//print_r($news);die;
$news->view_count = intval($this->view_count + $view_count);
$news->save();
}
}
//同步成功,删除redis数据
$this->redis->del($hash);
return '同步成功';
} catch (\Exception $e) {
return $e->getMessage();
}
}
// Redis 哈希表的命名,如:news_view_counts_2020-07-13
private function getHashFromDateString()
{
return $this->hash_prefix . $this->date;
}
// 字段名称,如:news_1
private function getHashField()
{
return $this->field_prefix . $this->id;
}
}
发表评论 取消回复