最近在工作中遇到一个需求,要面向所有用户发送公告,用户可以删除或者设为已读。这个用数据没办法去实现,我用redis模拟结合数据的方式去实现这个功能。说了这么多废话,还是来点干货吧。
直接贴代码
<?php
/**
* 消息列表类
* redis key类型为 set
* yxt_notice_read_ 已读列表(表后缀 uid除以1000)
* 存储方式: 键值 消息id 用户id(逗号拼接)
* yxt_notice_del 已读列表
* 存储方式: 键值 用户id 消息id(逗号拼接)
* author fong
*/
class MessageBox extends Redis
{
public $uid;
private $readListKey='yxt_notice_read_';
private $delListKey ='yxt_notice_del';
public $mid; //消息id
private $listSize=1000;
private $init = false;
public function __construct()
{
$this->connect(config('redis.host'), config('redis.port'));
$this->auth(config('redis.password'));
}
//添加一条已读信息
public function read($uid,$mid){
$this->uid = $uid;
$this->mid = $mid;
$this->buildKey();
$res = $this->hGet($this->readListKey,$this->mid);
if(isset($res) && in_array($this->uid,explode(',',$res))) return;
if(empty($res)) $res='';
$this->hSet($this->readListKey,$this->mid,$res.','.$this->uid);
}
public function getIndexKey(){
return ceil( $this->uid / $this->listSize );
}
//删除一条已读信息
public function del($uid,$mid){
$this->uid = $uid;
$this->mid = $mid;
$this->buildKey();
$res = $this->hGet($this->delListKey,$this->uid);
if(isset($res) && in_array($this->mid,explode(',',$res))) return;
if(empty($res)) $res='';
$this->hSet($this->delListKey,$this->uid,$res.','.$this->mid);
}
//拼接已读列表键值
public function buildKey(){
if($this->init) return; //防止多次循环的时候,改变键值
$this->readListKey = $this->readListKey.$this->getIndexKey() ;
$this->init = true;
}
//获取用户已读列表
public function getReadList($uid){
$this->uid = $uid;
$this->buildKey();
$res = $this->hGetAll($this->readListKey);
foreach ( $res as $k=>$v ) {
if(in_array($uid,explode(',',$v))){
$lists[] = $k;
}
}
return $lists;
}
//获取用户已删除的列表
public function getDelList($uid){
$this->uid = $uid;
$this->buildKey();
// var_dump($this->hGet($this->delListKey,$this->uid));die;
return trim($this->hGet($this->delListKey,$this->uid),',');
}
}
热门评论
消息不存到数据库吗