php实现日历签到
实现日历签到功能
日历签到功能通常包括用户每日签到记录、连续签到统计以及奖励机制。以下是实现这一功能的详细步骤:
数据库设计
创建签到记录表,包含用户ID、签到日期和连续签到天数等字段:

CREATE TABLE user_checkins (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
checkin_date DATE NOT NULL,
consecutive_days INT DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY (user_id, checkin_date)
);
签到逻辑处理
编写PHP代码处理签到请求,检查用户是否已签到并更新连续签到天数:
function handleCheckin($userId) {
$today = date('Y-m-d');
$pdo = new PDO('mysql:host=localhost;dbname=your_db', 'username', 'password');
// 检查今日是否已签到
$stmt = $pdo->prepare("SELECT * FROM user_checkins WHERE user_id = ? AND checkin_date = ?");
$stmt->execute([$userId, $today]);
if ($stmt->rowCount() > 0) {
return ['status' => 'error', 'message' => '今日已签到'];
}
// 获取昨日签到记录
$yesterday = date('Y-m-d', strtotime('-1 day'));
$stmt = $pdo->prepare("SELECT consecutive_days FROM user_checkins WHERE user_id = ? AND checkin_date = ?");
$stmt->execute([$userId, $yesterday]);
$consecutiveDays = $stmt->rowCount() > 0 ? $stmt->fetch()['consecutive_days'] + 1 : 1;
// 记录今日签到
$stmt = $pdo->prepare("INSERT INTO user_checkins (user_id, checkin_date, consecutive_days) VALUES (?, ?, ?)");
$stmt->execute([$userId, $today, $consecutiveDays]);
return ['status' => 'success', 'consecutive_days' => $consecutiveDays];
}
日历显示实现
生成日历视图并标记已签到日期:

function generateCalendar($userId, $year, $month) {
$pdo = new PDO('mysql:host=localhost;dbname=your_db', 'username', 'password');
$stmt = $pdo->prepare("SELECT checkin_date FROM user_checkins WHERE user_id = ? AND YEAR(checkin_date) = ? AND MONTH(checkin_date) = ?");
$stmt->execute([$userId, $year, $month]);
$signedDates = array_column($stmt->fetchAll(), 'checkin_date');
$daysInMonth = date('t', mktime(0, 0, 0, $month, 1, $year));
$calendar = [];
for ($day = 1; $day <= $daysInMonth; $day++) {
$date = sprintf('%04d-%02d-%02d', $year, $month, $day);
$calendar[$day] = [
'date' => $date,
'signed' => in_array($date, $signedDates)
];
}
return $calendar;
}
前端展示
使用HTML/CSS展示日历和签到按钮:
<div class="calendar">
<?php foreach ($calendar as $day => $data): ?>
<div class="day <?= $data['signed'] ? 'signed' : '' ?>">
<span class="date"><?= $day ?></span>
<?= $data['signed'] ? '✓' : '' ?>
</div>
<?php endforeach; ?>
</div>
<button id="checkin-btn" onclick="handleCheckin()">每日签到</button>
奖励机制实现
根据连续签到天数发放奖励:
function giveReward($userId, $consecutiveDays) {
$rewards = [
3 => ['type' => 'points', 'amount' => 100],
7 => ['type' => 'points', 'amount' => 300],
30 => ['type' => 'vip', 'days' => 1]
];
if (isset($rewards[$consecutiveDays])) {
$reward = $rewards[$consecutiveDays];
// 实现发放奖励的逻辑
return $reward;
}
return null;
}
注意事项
- 使用事务处理确保数据一致性
- 考虑时区问题,使用服务器统一时区处理日期
- 添加适当的错误处理和日志记录
- 前端可添加动画效果增强用户体验
- 对于高并发场景,考虑使用Redis等缓存技术优化性能
实现日历签到功能时,应根据具体业务需求调整数据库结构和奖励规则。定期清理历史签到数据可优化数据库性能。






