通过使用ThinkPHP 行为类(Behavior),钩子(Hook) 机制自动执行用户活跃统计。
目录
创建数据表
首先设计数据表,需要区分注册登录与其他行为。
数据表结构如下:
sql
CREATE TABLE `fa_user_active` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL COMMENT '用户ID',
`active_type` tinyint(2) NOT NULL COMMENT '类型:1=登录,2=页面访问',
`active_time` int(11) NOT NULL COMMENT '活跃时间戳',
`ip` varchar(50) NOT NULL DEFAULT '' COMMENT 'IP地址',
`url` varchar(255) NOT NULL DEFAULT '' COMMENT '访问URL',
`module` varchar(20) NOT NULL DEFAULT '' COMMENT '模块(admin/index)',
`controller` varchar(50) NOT NULL DEFAULT '' COMMENT '控制器',
`action` varchar(50) NOT NULL DEFAULT '' COMMENT '方法',
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_user_id` (`user_id`) USING BTREE,
KEY `idx_active_time` (`active_time`) USING BTREE,
KEY `idx_user_time` (`user_id`,`active_time`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户活跃统计表';
创建模型层
在application/common/model中创建模型层UserActive.php文件,代码如下:
php
<?php
namespace app\common\model;
use think\Model;
class UserActive extends Model
{
protected $name = 'user_active';
// 自动写入时间戳字段
protected $autoWriteTimestamp = false;
// 定义时间戳字段名
protected $createTime = false;
protected $updateTime = false;
protected $deleteTime = false;
// 设置返回数据集的对象名
protected $resultSetType = 'collection';
// 追加属性
protected $append = [];
}
创建behavior文件
在application/api中创建behavior文件夹,然后创建UserActiveBehavior.php文件。
代码如下:
php
<?php
namespace app\api\behavior;
use app\common\library\Auth;
use think\Request;
use app\common\model\UserActive;
/**
* 用户活跃统计行为(替代中间件)
*/
class UserActiveBehavior
{
/**
* 绑定到 action_begin 钩子(控制器方法执行前触发)
* @param Request $request 请求对象
*/
public function run($request)
{
$request = Request::instance();
// 排除不需要统计的URL(静态资源、登录/注册等)
$exceptUris = [
// 登录/注册页
'api/user/login',
'api/user/mobilelogin',
'api/user/third',
'api/user/register',
// 静态资源/接口
'uploads',
'captcha',
];
// 获取当前请求的 模块/控制器/方法
$module = $request->module();
$controller = $request->controller();
$action = $request->action();
$currentUri = strtolower("{$module}/{$controller}/{$action}");
// 跳过排除的URL
foreach ($exceptUris as $uri) {
if (strpos($currentUri, strtolower($uri)) !== false) {
return;
}
}
// 仅记录已登录用户的访问行为
$user = Auth::instance()->getUser();
if ($user) {
$uid = $user->id;
// 防重复:5分钟内同一URL只记录一次(避免高频访问重复入库)
$cacheKey = "user_active_{$uid}_{$currentUri}";
if (!cache($cacheKey)) {
// 插入活跃统计表
UserActive::create([
'user_id' => $uid,
'active_type' => 2, // 2=页面访问
'active_time' => time(),
'ip' => $request->header('x-real-ip') ?? $request->ip(),
'url' => $request->url(),
'module' => $module,
'controller' => $controller,
'action' => $action,
]);
// 缓存5分钟
cache($cacheKey, 1, 300);
}
}
}
}
注册活跃统计
在application/api下创建tags.php文件,在tags.php文件中注册活跃统计类,
代码如下:
php
<?php
// 行为扩展定义文件
return [
// 绑定 action_begin 钩子(控制器方法执行前触发)
'action_begin' => [
'app\api\behavior\UserActiveBehavior', // 注册用户活跃统计行为
],
];
注册登录添加
在注册登录业务中增加活跃统计,因为在活跃统计类中会过滤掉此项统计,所以需要特别添加。
代码如下:
php
// 增加用户活跃记录
\app\common\model\UserActive::create([
'user_id' => $user->id,
'active_type' => 1,
'active_time' => time(),
'ip' => $ip,
'module' => request()->module(),
'controller' => request()->controller(),
'action' => request()->action(),
]);
总结
这样在使用api模块时,就会经过注册的用户活跃统计类,对用户行为进行统计;
还可以在后台进行统计折线图展示。