本文目录导读:

我来为你详细介绍PHP注册邀请码机制的实现方案。
数据库设计
邀请码表
CREATE TABLE `invite_codes` ( `id` int(11) NOT NULL AUTO_INCREMENT, `code` varchar(20) NOT NULL COMMENT '邀请码', `user_id` int(11) DEFAULT NULL COMMENT '生成邀请码的用户ID', `status` tinyint(1) DEFAULT '0' COMMENT '状态:0未使用,1已使用,2已过期', `used_by` int(11) DEFAULT NULL COMMENT '使用该邀请码的用户ID', `used_at` datetime DEFAULT NULL COMMENT '使用时间', `expire_at` datetime DEFAULT NULL COMMENT '过期时间', `created_at` timestamp DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_code` (`code`), KEY `idx_user_id` (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
用户表设计
CREATE TABLE `users` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL, `password` varchar(255) NOT NULL, `email` varchar(100) DEFAULT NULL, `invited_by` int(11) DEFAULT NULL COMMENT '邀请人用户ID', `created_at` timestamp DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_username` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
核心PHP代码实现
邀请码生成类
<?php
class InviteCode {
private $db;
public function __construct($db) {
$this->db = $db;
}
/**
* 生成邀请码
* @param int $userId 用户ID
* @param int $count 生成数量
* @param int $expireDays 过期天数
* @return array 生成的邀请码
*/
public function generate($userId, $count = 1, $expireDays = 30) {
$codes = [];
$expireAt = date('Y-m-d H:i:s', strtotime("+{$expireDays} days"));
for ($i = 0; $i < $count; $i++) {
$code = $this->generateUniqueCode();
$sql = "INSERT INTO invite_codes (code, user_id, expire_at) VALUES (?, ?, ?)";
$stmt = $this->db->prepare($sql);
$stmt->bind_param("sis", $code, $userId, $expireAt);
if ($stmt->execute()) {
$codes[] = $code;
}
}
return $codes;
}
/**
* 生成唯一邀请码
*/
private function generateUniqueCode() {
$characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$code = '';
$max = strlen($characters) - 1;
do {
$code = '';
for ($i = 0; $i < 8; $i++) {
$code .= $characters[random_int(0, $max)];
}
} while ($this->codeExists($code));
return $code;
}
/**
* 检查邀请码是否已存在
*/
private function codeExists($code) {
$sql = "SELECT id FROM invite_codes WHERE code = ?";
$stmt = $this->db->prepare($sql);
$stmt->bind_param("s", $code);
$stmt->execute();
$result = $stmt->get_result();
return $result->num_rows > 0;
}
/**
* 验证邀请码
*/
public function validate($code) {
$sql = "SELECT * FROM invite_codes WHERE code = ? AND status = 0";
$stmt = $this->db->prepare($sql);
$stmt->bind_param("s", $code);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows === 0) {
return ['valid' => false, 'message' => '邀请码不存在或已被使用'];
}
$inviteCode = $result->fetch_assoc();
// 检查过期
if (strtotime($inviteCode['expire_at']) < time()) {
return ['valid' => false, 'message' => '邀请码已过期'];
}
return ['valid' => true, 'data' => $inviteCode];
}
/**
* 使用邀请码
*/
public function useCode($code, $userId) {
$sql = "UPDATE invite_codes
SET status = 1, used_by = ?, used_at = NOW()
WHERE code = ? AND status = 0";
$stmt = $this->db->prepare($sql);
$stmt->bind_param("is", $userId, $code);
return $stmt->execute();
}
/**
* 获取用户的邀请记录
*/
public function getInviteRecords($userId) {
$sql = "SELECT u.username, u.created_at
FROM users u
WHERE u.invited_by = ?";
$stmt = $this->db->prepare($sql);
$stmt->bind_param("i", $userId);
$stmt->execute();
return $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
}
}
注册处理逻辑
<?php
class Register {
private $db;
private $inviteCode;
public function __construct($db) {
$this->db = $db;
$this->inviteCode = new InviteCode($db);
}
/**
* 注册新用户
*/
public function register($username, $password, $invite_code = '') {
// 1. 验证输入
if (empty($username) || empty($password)) {
return ['success' => false, 'message' => '用户名和密码不能为空'];
}
// 2. 检查用户名是否已存在
if ($this->usernameExists($username)) {
return ['success' => false, 'message' => '用户名已存在'];
}
// 3. 验证邀请码(如果开启强制邀请)
if (!empty($invite_code)) {
$inviteValidation = $this->inviteCode->validate($invite_code);
if (!$inviteValidation['valid']) {
return ['success' => false, 'message' => $inviteValidation['message']];
}
} elseif ($this->requireInviteCode()) {
return ['success' => false, 'message' => '请填写邀请码'];
}
// 4. 创建用户
$invitedBy = null;
if (!empty($invite_code) && $inviteValidation['valid']) {
$invitedBy = $inviteValidation['data']['user_id'];
}
$passwordHash = password_hash($password, PASSWORD_BCRYPT);
$sql = "INSERT INTO users (username, password, invited_by) VALUES (?, ?, ?)";
$stmt = $this->db->prepare($sql);
$stmt->bind_param("ssi", $username, $passwordHash, $invitedBy);
if ($stmt->execute()) {
$userId = $stmt->insert_id;
// 5. 标记邀请码为已使用
if (!empty($invite_code)) {
$this->inviteCode->useCode($invite_code, $userId);
}
return ['success' => true, 'message' => '注册成功', 'user_id' => $userId];
}
return ['success' => false, 'message' => '注册失败'];
}
private function usernameExists($username) {
$sql = "SELECT id FROM users WHERE username = ?";
$stmt = $this->db->prepare($sql);
$stmt->bind_param("s", $username);
$stmt->execute();
return $stmt->get_result()->num_rows > 0;
}
private function requireInviteCode() {
// 这里可以配置是否需要强制邀请码
return true;
}
}
控制器/接口示例
<?php
// 处理注册请求
class RegisterController {
public function handleRegister() {
// 模拟数据库连接
$db = new mysqli('localhost', 'user', 'password', 'database');
$register = new Register($db);
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
$inviteCode = $_POST['invite_code'] ?? '';
$result = $register->register($username, $password, $inviteCode);
header('Content-Type: application/json');
echo json_encode($result);
}
// 生成邀请码接口(仅限已登录用户)
public function generateInviteCodes() {
session_start();
if (!isset($_SESSION['user_id'])) {
echo json_encode(['success' => false, 'message' => '请先登录']);
return;
}
$db = new mysqli('localhost', 'user', 'password', 'database');
$inviteCode = new InviteCode($db);
$count = $_POST['count'] ?? 1;
$expireDays = $_POST['expire_days'] ?? 30;
$codes = $inviteCode->generate($_SESSION['user_id'], $count, $expireDays);
echo json_encode(['success' => true, 'codes' => $codes]);
}
}
用户体验优化
前端表单示例
<!DOCTYPE html>
<html>
<head>注册</title>
</head>
<body>
<form id="registerForm">
<input type="text" name="username" placeholder="用户名" required>
<input type="password" name="password" placeholder="密码" required>
<input type="text" name="invite_code" placeholder="邀请码(必填)" required>
<button type="submit">注册</button>
</form>
<script>
document.getElementById('registerForm').addEventListener('submit', function(e) {
e.preventDefault();
// 使用ajax提交数据
});
</script>
</body>
</html>
邀请码状态检查
// 检查邀请码状态(AJAX接口)
public function checkInviteCode() {
$code = $_GET['code'] ?? '';
$inviteCode = new InviteCode($db);
$result = $inviteCode->validate($code);
if ($result['valid']) {
echo json_encode(['valid' => true, 'message' => '邀请码有效']);
} else {
echo json_encode(['valid' => false, 'message' => $result['message']]);
}
}
安全考虑与最佳实践
- 防并发问题:使用事务处理邀请码的使用
- 数据验证:严格验证所有输入
- SQL注入防护:使用预处理语句
- 邀请码长度:建议使用8-10位,包含字母和数字
- 过期策略:设置合理的过期时间
- 使用次数限制:限制单个用户可生成的邀请码数量
- 日志记录:记录所有邀请码的生成和使用记录
- 定期清理:定期清理过期的邀请码
这就是一个完整的PHP注册邀请码机制实现,可以根据实际需求进行调整和扩展。