PHP+MySQL高仿百度知道签到系统:从零到一实战指南

PHP+MySQL高仿百度知道签到系统:从零到一实战指南

一、系统需求分析与功能设计

1.1 核心功能拆解

百度知道签到系统的核心功能包括:每日签到奖励机制、连续签到额外奖励、签到历史记录查询、积分体系与等级成长。这些功能需通过PHP后端逻辑与MySQL数据库交互实现,其中签到状态管理、连续签到天数计算、奖励发放逻辑是开发重点。

1.2 数据库表结构设计

  1. CREATE TABLE `users` (
  2. `id` INT AUTO_INCREMENT PRIMARY KEY,
  3. `username` VARCHAR(50) NOT NULL UNIQUE,
  4. `password` VARCHAR(255) NOT NULL,
  5. `points` INT DEFAULT 0,
  6. `level` INT DEFAULT 1
  7. );
  8. CREATE TABLE `sign_records` (
  9. `id` INT AUTO_INCREMENT PRIMARY KEY,
  10. `user_id` INT NOT NULL,
  11. `sign_date` DATE NOT NULL,
  12. `consecutive_days` INT DEFAULT 0,
  13. FOREIGN KEY (`user_id`) REFERENCES `users`(`id`)
  14. );

用户表存储基础信息与积分等级,签到记录表通过外键关联用户,记录每日签到状态与连续天数。连续签到天数需在签到时动态计算,而非直接存储,以保证数据一致性。

二、核心功能实现

2.1 签到状态验证与更新

  1. function handleSignIn($userId) {
  2. $today = date('Y-m-d');
  3. $db = new PDO('mysql:host=localhost;dbname=sign_system', 'username', 'password');
  4. // 检查今日是否已签到
  5. $stmt = $db->prepare("SELECT * FROM sign_records WHERE user_id = ? AND sign_date = ?");
  6. $stmt->execute([$userId, $today]);
  7. if ($stmt->rowCount() > 0) {
  8. return ['status' => 'failed', 'message' => '今日已签到'];
  9. }
  10. // 计算连续签到天数
  11. $lastSignDate = null;
  12. $consecutiveDays = 1;
  13. $stmt = $db->prepare("SELECT sign_date FROM sign_records WHERE user_id = ? ORDER BY sign_date DESC LIMIT 1");
  14. $stmt->execute([$userId]);
  15. if ($row = $stmt->fetch()) {
  16. $lastSignDate = $row['sign_date'];
  17. $lastDay = new DateTime($lastSignDate);
  18. $todayObj = new DateTime($today);
  19. $interval = $lastDay->diff($todayObj);
  20. if ($interval->d === 1 && $todayObj->format('m') === $lastDay->format('m') && $todayObj->format('Y') === $lastDay->format('Y')) {
  21. $consecutiveDays = (int)$db->query("SELECT consecutive_days FROM sign_records WHERE user_id = $userId AND sign_date = '$lastSignDate'")->fetchColumn() + 1;
  22. } else {
  23. $consecutiveDays = 1; // 断签重置
  24. }
  25. }
  26. // 插入新签到记录
  27. $stmt = $db->prepare("INSERT INTO sign_records (user_id, sign_date, consecutive_days) VALUES (?, ?, ?)");
  28. $stmt->execute([$userId, $today, $consecutiveDays]);
  29. // 更新用户积分(基础5分+连续签到奖励)
  30. $pointsToAdd = 5 + ($consecutiveDays >= 3 ? ($consecutiveDays - 2) * 2 : 0); // 示例:连续3天起每天+2分
  31. $db->prepare("UPDATE users SET points = points + ? WHERE id = ?")->execute([$pointsToAdd, $userId]);
  32. return ['status' => 'success', 'message' => '签到成功', 'points' => $pointsToAdd, 'consecutiveDays' => $consecutiveDays];
  33. }

关键逻辑包括:通过日期差判断是否连续签到、动态计算连续天数、根据规则发放积分奖励。连续签到计算需考虑跨月情况,建议使用DateTime类精确处理。

2.2 签到历史查询接口

  1. function getSignHistory($userId, $month) {
  2. $db = new PDO('mysql:host=localhost;dbname=sign_system', 'username', 'password');
  3. $startDate = date('Y-m-d', strtotime($month . '-01'));
  4. $endDate = date('Y-m-t', strtotime($startDate));
  5. $stmt = $db->prepare("
  6. SELECT sign_date, consecutive_days
  7. FROM sign_records
  8. WHERE user_id = ? AND sign_date BETWEEN ? AND ?
  9. ORDER BY sign_date DESC
  10. ");
  11. $stmt->execute([$userId, $startDate, $endDate]);
  12. $history = [];
  13. while ($row = $stmt->fetch()) {
  14. $history[] = [
  15. 'date' => $row['sign_date'],
  16. 'consecutive' => $row['consecutive_days']
  17. ];
  18. }
  19. return $history;
  20. }

通过日期范围查询实现按月查看功能,前端可结合日历组件展示签到状态。

三、前端交互与用户体验优化

3.1 AJAX异步签到流程

  1. // jQuery示例
  2. $('#signInBtn').click(function() {
  3. $.ajax({
  4. url: 'sign_in.php',
  5. type: 'POST',
  6. data: {userId: 123}, // 实际应从cookie或session获取
  7. success: function(response) {
  8. if (response.status === 'success') {
  9. $('#points').text(parseInt($('#points').text()) + response.points);
  10. $('#consecutiveDays').text(response.consecutiveDays);
  11. alert('签到成功!获得' + response.points + '积分');
  12. } else {
  13. alert(response.message);
  14. }
  15. },
  16. error: function() {
  17. alert('网络错误,请重试');
  18. }
  19. });
  20. });

异步请求避免页面刷新,提升用户体验。后端需设置header('Content-Type: application/json')返回JSON格式数据。

3.2 日历组件集成

推荐使用FullCalendar或自定义HTML表格展示签到状态:

  1. <table id="calendar">
  2. <tr>
  3. <th></th><th></th><!-- ... -->
  4. </tr>
  5. <!-- 通过PHP动态生成日期格子 -->
  6. <?php
  7. $daysInMonth = cal_days_in_month(CAL_GREGORIAN, date('m'), date('Y'));
  8. $firstDay = date('w', strtotime(date('Y-m') . '-01')); // 0(日)~6(六)
  9. for ($i = 0; $i < $firstDay; $i++) echo '<td></td>';
  10. for ($day = 1; $day <= $daysInMonth; $day++) {
  11. $currentDate = date('Y-m') . '-' . str_pad($day, 2, '0', STR_PAD_LEFT);
  12. $isSigned = $db->query("SELECT 1 FROM sign_records WHERE user_id = 123 AND sign_date = '$currentDate'")->rowCount() > 0;
  13. echo '<tdpln"> . ($isSigned ? 'signed' : '') . '">' . $day . '</td>';
  14. if (($day + $firstDay) % 7 === 0) echo '</tr><tr>';
  15. }
  16. ?>
  17. </table>

通过CSS为已签到日期添加背景色(.signed { background-color: #e6f7ff; })。

四、安全与性能优化

4.1 防重复签到机制

  • 前端限制:按钮点击后禁用,防止重复提交
  • 后端验证:数据库唯一约束+应用层检查
    1. ALTER TABLE sign_records ADD UNIQUE KEY `unique_sign` (`user_id`, `sign_date`);

    唯一索引确保同一用户同一天只能有一条记录。

4.2 SQL注入防护

所有SQL语句必须使用预处理:

  1. // 错误示例(存在注入风险)
  2. $userId = $_POST['userId'];
  3. $db->query("SELECT * FROM users WHERE id = $userId");
  4. // 正确做法
  5. $stmt = $db->prepare("SELECT * FROM users WHERE id = ?");
  6. $stmt->execute([$userId]);

4.3 数据库索引优化

为高频查询字段添加索引:

  1. CREATE INDEX idx_user_date ON sign_records(user_id, sign_date);
  2. CREATE INDEX idx_username ON users(username);

索引可显著提升查询速度,尤其是历史记录查询场景。

五、部署与扩展建议

5.1 环境配置要求

  • PHP 7.4+ + MySQL 5.7+
  • 推荐使用Nginx + PHP-FPM
  • 开启OPcache加速:zend_extension=opcache.so; opcache.enable=1

5.2 扩展功能方向

  1. 多设备同步:通过Redis存储用户签到状态,实现多端实时同步
  2. 补签卡道具:增加积分商城兑换补签卡功能
  3. 签到排行榜:定期统计用户签到数据,展示活跃用户

六、完整源码获取方式

本文示例代码已精简核心逻辑,完整项目(含前端页面、数据库初始化脚本、详细注释)可通过GitHub获取:

  1. git clone https://github.com/yourrepo/php-sign-system.git

建议在实际项目中补充错误处理、日志记录等模块。

结语:本系统通过PHP+MySQL实现了百度知道签到系统的核心功能,开发者可根据实际需求调整积分规则、连续签到奖励策略等参数。实践过程中需特别注意安全性(如XSS防护、CSRF令牌)和性能优化(如缓存机制),建议结合Laravel等框架进一步提升开发效率。