前段时间做了一个页面停留时间的功能,用于统计客户在当前页面停留时间的统计,以方便统计用户喜欢浏览什么样的商品。
主要用到 php+redis心跳,代码仅为大家提供一下思路,如下。
数据库字段
mark ->标识 varchar
hashid ->hashid varchar
seconds -> 停留时间 int
nums -> 当前页面停留的总人数 int
members -> 会员id
****************************开始**************************************** //统计停留时间方法 public function record() { $params = $this->process_resttime(); //参数验证 $this->redis = new Redis(); $key = 'resttime:' . $params['mark'] . ':' . $params['hashid'] . ':' . $params['member_id']; $max_seconds = $this->redis_get($key); //页面最大停留时间记录为180s,超过则不统计,去除用户页面停留后人不在一直统计情况 if ($max_seconds > 175) { return 180; } return $redis->redis_incrby($key, 5);//每5秒统计一次 } //redis存入时间数据 private redis_incrby($key,$value){ if(!$key || !$value){ return false; } if(!Redis::exists($key)){ $this->redis->set($key,0); } return $this->redis->incrby($key,5); } //获取停留时间,判断是否超过最大停留时间限制 private function redis_get($key = []) { if (!$key) { return false; } return$this->redis->get($key);}
//活动标识跟活动 hashid来确定唯一的一个页面
//duration 前端轮询时间间隔
//member_id 会员id
private function process_resttime()
{
$this->validateRequest([
'duration' => 'required|numeric',
'mark' => 'required|alpha_dash',
'hashid' => 'required|alpha_dash',
'member_id' => 'required|alpha_dash',
], [
'duration' => '轮询时间',
'mark' => '活动标识',
'hashid' => '活动hashid',
'member_id' => '会员id',
]);
return [
'duration' => intval($this->input['duration']),
'mark' => trim($this->input['mark']),
'hashid' => trim($this->input['hashid']),
'member_id' => trim($this->input['member_id']),
];
}
***************************统计结束********************************
//获取统计数据
*****************************获取停留时间***************************
public function get_times(){
$this->validateRequest([
'mark' => 'required|alpha_dash',
'hashid' => 'required|alpha_dash',
], [
'mark' => '活动标识',
'hashid' => '活动hashid',
]);
$key = 'resttime:'.$this->input['mark'].':'.$this->input['hashid'];
$this->redis = new Redis();
$keys = $this->redis->redis_keys($key);
$average_times = $this->process_times($keys);
return $average_times ? ['times'=>$average_times] : 0;
}
private function redis_keys($key = []){
if (!$key) {
return false;
}
$this->_init_redis();
return $this->redis->keys($key.'*');
}
private function process_times($keys){
if($keys && is_array($keys)){
$datas = $this->redis->redis_mget($keys);
$times = array_sum($datas);
$members = $this->get_members($keys);//获取会员id数组
$raw_data = [
'mark' => $this->input['mark'],
'hashid' => $this->input['hashid'],
'seconds'=> $times ? intval($times) : 0,
'nums' => $keys ? count($keys) :0 ,
'members'=> $members ? serialize($members) :'' ,
];
$id = Resttime::insertGetId($raw_data);
if($id){
//取出缓存,删除原先缓存数据
$this->redis->redis_del($keys);
}
}
$seconds = Resttime::where(['mark'=>$this->input['mark'],'hashid'=>$this->input['hashid']])->sum('seconds');//获取该活动总停留秒数
$data = Resttime::select('members')->where(['mark'=>$this->input['mark'],'hashid'=>$this->input['hashid']])->get()->toArray();
$nums = $this->process_nums($data);//获取活动会员数,剔除重复的会员
$average_times = number_format($seconds/$nums,2);
return $average_times ? :0;
}
private function redis_mget($key = []){
if (!$key) {
return false;
}
return $this->redis->mget($key);
}
//处理会员人数,防止重复统计
private function get_members($keys){
foreach ($keys as $oo){
$members[] = explode(':',$oo)['3'];
}
return $members ? :'';
}
private function redis_del($key = ''){
if (!$key) {
return false;
}
return $this->redis->del($key);
}
private function process_nums($data){
$datas = [];
if($data && is_array($data)) {
foreach ($data as $key => $vo){
$datas[] = $vo['members'] ? unserialize($vo['members']) :[];
}
}
$result = array_reduce($datas, 'array_merge', []);
$nums = count(array_unique($result));
return $nums ? :1;
}
*******************************************结束***********************************************