本文目录导读:

我来详细介绍PHP实现防沉迷系统的几种方案:
基础实名认证 + 时间控制
数据库设计
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
id_card VARCHAR(18) NOT NULL, -- 身份证号
real_name VARCHAR(50) NOT NULL,
birthday DATE NOT NULL, -- 出生日期
status TINYINT DEFAULT 1, -- 1:正常 0:冻结
created_at TIMESTAMP
);
CREATE TABLE play_records (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
play_date DATE NOT NULL,
start_time DATETIME,
end_time DATETIME,
duration INT DEFAULT 0, -- 累计时长(分钟)
FOREIGN KEY (user_id) REFERENCES users(id)
);
核心防沉迷逻辑
年龄验证类
<?php
class AntiAddiction {
private $db;
public function __construct($db) {
$this->db = $db;
}
/**
* 根据身份证号计算年龄
*/
public function calculateAge($idCard) {
// 获取出生日期 (身份证第7-14位)
$birthday = substr($idCard, 6, 8);
$birthYear = substr($birthday, 0, 4);
$birthMonth = substr($birthday, 4, 2);
$birthDay = substr($birthday, 6, 2);
$birthDate = new DateTime("$birthYear-$birthMonth-$birthDay");
$now = new DateTime();
$age = $now->diff($birthDate)->y;
return $age;
}
/**
* 获取防沉迷策略
*/
public function getPolicy($age) {
if ($age < 8) {
return [
'allowed' => false,
'daily_limit' => 0, // 不允许游戏
'night_ban' => null, // 完全禁止
'message' => '未满8周岁用户无法使用游戏服务'
];
} elseif ($age < 16) {
return [
'allowed' => true,
'daily_limit' => 60, // 每天1小时
'night_ban' => ['22:00', '08:00'], // 晚上10点至早8点禁止
'message' => '未成年人需合理安排游戏时间'
];
} elseif ($age < 18) {
return [
'allowed' => true,
'daily_limit' => 120, // 每天2小时
'night_ban' => ['22:00', '08:00'],
'message' => '未成年人需合理安排游戏时间'
];
} elseif ($age >= 18) {
return [
'allowed' => true,
'daily_limit' => null, // 成年人不限制
'night_ban' => null,
'message' => '成年人请适度游戏'
];
}
}
/**
* 检查游戏状态
*/
public function checkPlayStatus($userId) {
// 获取用户信息
$user = $this->getUser($userId);
if (!$user) {
return ['code' => 404, 'msg' => '用户不存在'];
}
// 计算用户年龄
$age = $this->calculateAge($user['id_card']);
$policy = $this->getPolicy($age);
// 未满8岁
if (!$policy['allowed']) {
return [
'code' => 403,
'can_play' => false,
'msg' => $policy['message']
];
}
// 检查夜间限制
$now = date('H:i');
if ($policy['night_ban']) {
list($start, $end) = $policy['night_ban'];
if ($this->isNightTime($now, $start, $end)) {
return [
'code' => 403,
'can_play' => false,
'msg' => "当前时间($now)限制登录"
];
}
}
// 检查今日累计时长
$todayDuration = $this->getTodayDuration($userId);
if ($policy['daily_limit'] && $todayDuration >= $policy['daily_limit']) {
return [
'code' => 403,
'can_play' => false,
'msg' => '今日游戏时间已达上限'
];
}
return [
'code' => 200,
'can_play' => true,
'remaining_time' => $policy['daily_limit'] - $todayDuration,
'policy' => $policy
];
}
/**
* 记录游戏开始
*/
public function startPlay($userId) {
$status = $this->checkPlayStatus($userId);
if (!$status['can_play']) {
return $status;
}
$today = date('Y-m-d');
$record = $this->db->query(
"SELECT * FROM play_records WHERE user_id=$userId AND play_date='$today'"
)->fetch_assoc();
if ($record) {
// 继续昨天的记录或者创建新记录
$this->db->query(
"UPDATE play_records SET start_time=NOW() WHERE id={$record['id']}"
);
} else {
$this->db->query(
"INSERT INTO play_records (user_id, play_date, start_time)
VALUES ($userId, '$today', NOW())"
);
}
return ['code' => 200, 'msg' => '开始游戏'];
}
/**
* 记录游戏结束
*/
public function endPlay($userId) {
$today = date('Y-m-d');
$record = $this->db->query(
"SELECT * FROM play_records
WHERE user_id=$userId AND play_date='$today' AND end_time IS NULL
ORDER BY id DESC LIMIT 1"
)->fetch_assoc();
if ($record) {
$endTime = time();
$startTime = strtotime($record['start_time']);
$duration = ($endTime - $startTime) / 60; // 分钟
$this->db->query(
"UPDATE play_records
SET end_time=NOW(),
duration=duration + $duration
WHERE id={$record['id']}"
);
}
return ['code' => 200, 'msg' => '游戏结束'];
}
/**
* 获取今日累计时长
*/
private function getTodayDuration($userId) {
$today = date('Y-m-d');
$result = $this->db->query(
"SELECT SUM(duration) as total
FROM play_records
WHERE user_id=$userId AND play_date='$today'"
)->fetch_assoc();
return $result['total'] ?? 0;
}
/**
* 判断是否处于夜间禁止时段
*/
private function isNightTime($now, $start, $end) {
$now = strtotime($now);
$start = strtotime($start);
$end = strtotime($end);
// 如果结束时间小于开始时间,说明跨天
if ($end < $start) {
return ($now >= $start || $now <= $end);
}
return ($now >= $start && $now <= $end);
}
}
调用示例
// 使用示例
$db = new mysqli('localhost', 'username', 'password', 'database');
$anti = new AntiAddiction($db);
// 检查游戏状态
$result = $anti->checkPlayStatus(1);
if ($result['can_play']) {
echo "可以开始游戏,剩余时间:" . $result['remaining_time'] . "分钟";
$anti->startPlay(1);
} else {
echo $result['msg'];
exit;
}
// 游戏结束
$anti->endPlay(1);
API接口设计
<?php
// api.php
header('Content-Type: application/json');
$action = $_GET['action'] ?? '';
$userId = (int)($_POST['user_id'] ?? 0);
$anti = new AntiAddiction($db);
switch ($action) {
case 'check':
$result = $anti->checkPlayStatus($userId);
break;
case 'start':
$result = $anti->startPlay($userId);
break;
case 'end':
$result = $anti->endPlay($userId);
break;
default:
$result = ['code' => 400, 'msg' => 'Invalid action'];
}
echo json_encode($result);
高级功能补充
跨平台时长累计
// 使用session或redis存储跨端数据
class CrossPlatformCounter {
private $redis;
public function addTime($userId, $platform, $duration) {
$key = "user:{$userId}:playtime:".date('Y-m-d');
$this->redis->incrBy($key, $duration);
$this->redis->expire($key, 24*3600);
}
public function getTotalTime($userId) {
// 从各个平台汇总
return $this->redis->get("user:{$userId}:playtime:".date('Y-m-d'));
}
}
定时任务清理
// cron.php - 每天凌晨执行 $sql = "DELETE FROM play_records WHERE play_date < DATE_SUB(NOW(), INTERVAL 7 DAY)"; $db->query($sql);
前端配合
// 前端定时检查
setInterval(async () => {
const response = await fetch('/api.php?action=check', {
method: 'POST',
body: new URLSearchParams({ user_id: userId })
});
const data = await response.json();
if (!data.can_play) {
alert(data.msg);
// 强制退出游戏
location.href = '/logout.php';
}
}, 60000); // 每分钟检查一次
注意事项
- 安全验证:身份证号需加密存储,使用AES加密
- 防绕过:服务端强制校验,不仅依赖前端
- 实名制:接入第三方实名认证接口
- 日志记录:记录所有登录和登出行为
- 异常处理:处理时区问题、跨天计算
- 性能优化:使用Redis缓存高频查询
这个方案涵盖了基本的防沉迷需求,实际生产环境还需根据具体业务场景进行调整优化。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播