php 关注实现
PHP 实现关注功能的方法
实现关注功能通常涉及用户之间的关系管理,以下是几种常见的实现方式:
数据库设计 创建用户表和关注关系表,关注关系表通常包含关注者ID和被关注者ID两个字段:
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL
);
CREATE TABLE follows (
follower_id INT,
followed_id INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (follower_id, followed_id),
FOREIGN KEY (follower_id) REFERENCES users(id),
FOREIGN KEY (followed_id) REFERENCES users(id)
);
关注操作实现 使用PHP处理关注请求,检查是否已关注并执行插入操作:
function followUser($followerId, $followedId) {
$pdo = new PDO('mysql:host=localhost;dbname=your_db', 'username', 'password');
$stmt = $pdo->prepare("INSERT IGNORE INTO follows (follower_id, followed_id) VALUES (?, ?)");
$stmt->execute([$followerId, $followedId]);
return $stmt->rowCount() > 0;
}
取消关注实现 从关注关系表中删除对应记录:
function unfollowUser($followerId, $followedId) {
$pdo = new PDO('mysql:host=localhost;dbname=your_db', 'username', 'password');
$stmt = $pdo->prepare("DELETE FROM follows WHERE follower_id = ? AND followed_id = ?");
$stmt->execute([$followerId, $followedId]);
return $stmt->rowCount() > 0;
}
检查关注状态 查询两个用户之间是否存在关注关系:
function isFollowing($followerId, $followedId) {
$pdo = new PDO('mysql:host=localhost;dbname=your_db', 'username', 'password');
$stmt = $pdo->prepare("SELECT COUNT(*) FROM follows WHERE follower_id = ? AND followed_id = ?");
$stmt->execute([$followerId, $followedId]);
return $stmt->fetchColumn() > 0;
}
获取关注列表 查询某个用户关注的所有用户:
function getFollowingList($userId) {
$pdo = new PDO('mysql:host=localhost;dbname=your_db', 'username', 'password');
$stmt = $pdo->prepare("SELECT u.id, u.username FROM follows f JOIN users u ON f.followed_id = u.id WHERE f.follower_id = ?");
$stmt->execute([$userId]);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
获取粉丝列表 查询关注某个用户的所有用户:
function getFollowerList($userId) {
$pdo = new PDO('mysql:host=localhost;dbname=your_db', 'username', 'password');
$stmt = $pdo->prepare("SELECT u.id, u.username FROM follows f JOIN users u ON f.follower_id = u.id WHERE f.followed_id = ?");
$stmt->execute([$userId]);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
性能优化建议
对于大型社交平台,关注系统可能需要考虑以下优化措施:
缓存策略 使用Redis缓存热门用户的关注关系,减少数据库查询压力:
function getCachedFollowingCount($userId) {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$key = "user:{$userId}:following_count";
if (!$redis->exists($key)) {
$count = getFollowingCountFromDB($userId);
$redis->set($key, $count, 3600); // 缓存1小时
return $count;
}
return $redis->get($key);
}
批量处理 当需要处理大量关注关系时,使用批量插入提高效率:
function batchFollow($followerId, $followedIds) {
$pdo = new PDO('mysql:host=localhost;dbname=your_db', 'username', 'password');
$placeholders = implode(',', array_fill(0, count($followedIds), '?'));
$values = array_merge([$followerId], $followedIds);
$sql = "INSERT IGNORE INTO follows (follower_id, followed_id)
SELECT ? AS follower_id, id FROM users WHERE id IN ($placeholders)";
$stmt = $pdo->prepare($sql);
$stmt->execute($values);
return $stmt->rowCount();
}
分页查询 对于关注/粉丝列表实现分页功能:
function getPaginatedFollowing($userId, $page = 1, $perPage = 20) {
$offset = ($page - 1) * $perPage;
$pdo = new PDO('mysql:host=localhost;dbname=your_db', 'username', 'password');
$stmt = $pdo->prepare("SELECT u.id, u.username FROM follows f
JOIN users u ON f.followed_id = u.id
WHERE f.follower_id = ?
LIMIT ? OFFSET ?");
$stmt->bindValue(1, $userId, PDO::PARAM_INT);
$stmt->bindValue(2, $perPage, PDO::PARAM_INT);
$stmt->bindValue(3, $offset, PDO::PARAM_INT);
$stmt->execute();
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
安全考虑
实现关注功能时需要注意以下安全事项:
输入验证 对所有用户输入进行验证和过滤,防止SQL注入:
$followerId = filter_input(INPUT_POST, 'follower_id', FILTER_VALIDATE_INT);
$followedId = filter_input(INPUT_POST, 'followed_id', FILTER_VALIDATE_INT);
if (!$followerId || !$followedId) {
http_response_code(400);
echo json_encode(['error' => 'Invalid user IDs']);
exit;
}
权限检查 确保用户只能操作自己的关注关系:
session_start();
if ($_SESSION['user_id'] != $followerId) {
http_response_code(403);
echo json_encode(['error' => 'Unauthorized operation']);
exit;
}
防刷机制 限制用户频繁关注/取消关注操作:
function canPerformFollowAction($userId) {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$key = "user:{$userId}:follow_actions";
$count = $redis->incr($key);
if ($count == 1) {
$redis->expire($key, 60); // 60秒窗口
}
return $count <= 30; // 每分钟最多30次操作
}






