《PHP开发的互关注功能实现步骤介绍》
在社交类、社区类或用户互动型网站中,互关注功能是提升用户粘性和社交体验的核心模块。通过PHP实现互关注功能,需要结合数据库设计、业务逻辑处理和前端交互。本文将从功能需求分析、数据库设计、后端代码实现到前端交互,详细介绍互关注功能的完整实现步骤。
一、功能需求分析
互关注功能的核心需求包括:
用户A可以关注用户B
用户B可以关注用户A
当双方互相关注时,系统标记为"互相关注"状态
支持取消关注操作
实时更新关注状态(前端需无刷新更新)
扩展需求可能包括:
关注列表分页展示
粉丝数/关注数统计
关注推荐算法
二、数据库设计
实现互关注功能需要设计两张核心表:用户表和关注关系表。
1. 用户表(users)
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`password` varchar(255) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2. 关注关系表(follows)
该表记录用户间的关注关系,通过自关联设计实现:
CREATE TABLE `follows` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`follower_id` int(11) NOT NULL COMMENT '关注者ID',
`followee_id` int(11) NOT NULL COMMENT '被关注者ID',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_follow` (`follower_id`,`followee_id`),
KEY `followee_id` (`followee_id`),
CONSTRAINT `follows_ibfk_1` FOREIGN KEY (`follower_id`) REFERENCES `users` (`id`) ON DELETE CASCADE,
CONSTRAINT `follows_ibfk_2` FOREIGN KEY (`followee_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
关键设计点:
使用复合唯一索引(follower_id, followee_id)防止重复关注
外键约束保证数据完整性
created_at记录关注时间
三、PHP后端实现
后端实现分为三个核心部分:关注操作、取消关注操作和状态查询。
1. 关注操作实现
创建FollowController.php:
db = $db;
}
public function followUser($followerId, $followeeId) {
// 参数验证
if (!$followerId || !$followeeId || $followerId == $followeeId) {
return ['success' => false, 'message' => '无效的关注请求'];
}
// 检查是否已存在关注关系
$stmt = $this->db->prepare("SELECT id FROM follows WHERE follower_id = ? AND followee_id = ?");
$stmt->bind_param("ii", $followerId, $followeeId);
$stmt->execute();
$stmt->store_result();
if ($stmt->num_rows > 0) {
return ['success' => false, 'message' => '已关注过该用户'];
}
// 插入新关注关系
$insert = $this->db->prepare("INSERT INTO follows (follower_id, followee_id) VALUES (?, ?)");
$insert->bind_param("ii", $followerId, $followeeId);
if ($insert->execute()) {
return ['success' => true, 'message' => '关注成功'];
} else {
return ['success' => false, 'message' => '关注失败'];
}
}
}
2. 取消关注实现
public function unfollowUser($followerId, $followeeId) {
// 参数验证
if (!$followerId || !$followeeId || $followerId == $followeeId) {
return ['success' => false, 'message' => '无效的取消关注请求'];
}
// 删除关注关系
$stmt = $this->db->prepare("DELETE FROM follows WHERE follower_id = ? AND followee_id = ?");
$stmt->bind_param("ii", $followerId, $followeeId);
if ($stmt->execute()) {
if ($stmt->affected_rows > 0) {
return ['success' => true, 'message' => '取消关注成功'];
} else {
return ['success' => false, 'message' => '未找到关注关系'];
}
} else {
return ['success' => false, 'message' => '取消关注失败'];
}
}
3. 关注状态查询
需要查询三种状态:
当前用户是否关注目标用户
目标用户是否关注当前用户
是否互相关注
public function getFollowStatus($currentUserId, $targetUserId) {
$status = [
'isFollowing' => false,
'isFollowedBy' => false,
'isMutual' => false
];
// 查询当前用户是否关注目标用户
$stmt = $this->db->prepare("SELECT id FROM follows WHERE follower_id = ? AND followee_id = ?");
$stmt->bind_param("ii", $currentUserId, $targetUserId);
$stmt->execute();
$stmt->store_result();
$status['isFollowing'] = ($stmt->num_rows > 0);
// 查询目标用户是否关注当前用户
$stmt = $this->db->prepare("SELECT id FROM follows WHERE follower_id = ? AND followee_id = ?");
$stmt->bind_param("ii", $targetUserId, $currentUserId);
$stmt->execute();
$stmt->store_result();
$status['isFollowedBy'] = ($stmt->num_rows > 0);
// 互相关注状态
$status['isMutual'] = ($status['isFollowing'] && $status['isFollowedBy']);
return $status;
}
4. 关注数统计
public function getFollowCounts($userId) {
// 粉丝数(被多少人关注)
$stmt = $this->db->prepare("SELECT COUNT(*) as count FROM follows WHERE followee_id = ?");
$stmt->bind_param("i", $userId);
$stmt->execute();
$result = $stmt->get_result();
$followersCount = $result->fetch_assoc()['count'];
// 关注数(关注了多少人)
$stmt = $this->db->prepare("SELECT COUNT(*) as count FROM follows WHERE follower_id = ?");
$stmt->bind_param("i", $userId);
$stmt->execute();
$result = $stmt->get_result();
$followingCount = $result->fetch_assoc()['count'];
return [
'followers' => (int)$followersCount,
'following' => (int)$followingCount
];
}
四、API接口设计
采用RESTful风格设计API:
方法 | 路径 | 参数 | 描述 |
---|---|---|---|
POST | /api/follow | follower_id, followee_id | 关注用户 |
DELETE | /api/follow | follower_id, followee_id | 取消关注 |
GET | /api/follow/status | current_user_id, target_user_id | 获取关注状态 |
GET | /api/follow/counts | user_id | 获取关注数统计 |
示例关注API实现:
getConnection());
header('Content-Type: application/json');
$method = $_SERVER['REQUEST_METHOD'];
switch ($method) {
case 'POST':
$data = json_decode(file_get_contents('php://input'), true);
$result = $followController->followUser(
$data['follower_id'],
$data['followee_id']
);
echo json_encode($result);
break;
case 'DELETE':
parse_str(file_get_contents('php://input'), $deleteVars);
$result = $followController->unfollowUser(
$deleteVars['follower_id'],
$deleteVars['followee_id']
);
echo json_encode($result);
break;
default:
http_response_code(405);
echo json_encode(['message' => 'Method Not Allowed']);
}
五、前端交互实现
前端需要实现关注按钮的动态切换和状态更新。
1. HTML结构
2. JavaScript实现(使用Fetch API)
document.getElementById('follow-btn').addEventListener('click', async function() {
const btn = this;
const currentUserId = 1; // 当前登录用户ID
const targetUserId = 2; // 目标用户ID
try {
// 获取当前状态
const statusRes = await fetch(`/api/follow/status?current_user_id=${currentUserId}&target_user_id=${targetUserId}`);
const status = await statusRes.json();
let url, method;
if (status.isFollowing) {
// 已关注,执行取消关注
url = '/api/follow';
method = 'DELETE';
const formData = new URLSearchParams();
formData.append('follower_id', currentUserId);
formData.append('followee_id', targetUserId);
const body = formData.toString();
} else {
// 未关注,执行关注
url = '/api/follow';
method = 'POST';
const body = JSON.stringify({
follower_id: currentUserId,
followee_id: targetUserId
});
}
const response = await fetch(url, {
method: method,
headers: {
'Content-Type': method === 'POST' ? 'application/json' : 'application/x-www-form-urlencoded'
},
body: method === 'POST' ? body : new URLSearchParams(body)
});
const result = await response.json();
if (result.success) {
// 更新按钮文本和状态
if (status.isFollowing) {
btn.textContent = '关注';
btn.classList.remove('unfollow');
btn.classList.add('follow');
} else {
btn.textContent = '取消关注';
btn.classList.remove('follow');
btn.classList.add('unfollow');
}
// 更新关注数(可选)
updateFollowCounts(targetUserId);
} else {
alert(result.message);
}
} catch (error) {
console.error('操作失败:', error);
}
});
async function updateFollowCounts(userId) {
try {
const res = await fetch(`/api/follow/counts?user_id=${userId}`);
const counts = await res.json();
document.getElementById('follower-count').textContent = `粉丝数: ${counts.followers}`;
document.getElementById('following-count').textContent = `关注数: ${counts.following}`;
} catch (error) {
console.error('更新关注数失败:', error);
}
}
3. 按钮状态样式
.follow-btn {
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
}
.follow-btn.follow {
background-color: #1da1f2;
color: white;
}
.follow-btn.unfollow {
background-color: #f5f8fa;
color: #657786;
border: 1px solid #657786;
}
六、安全与性能优化
1. 安全措施
API接口添加身份验证(JWT或Session)
参数类型检查和值范围验证
防止SQL注入(使用预处理语句)
限制操作频率(防止刷关注)
2. 性能优化
关注关系表添加适当索引
使用缓存存储常用查询结果(如关注数)
批量操作处理(如同时关注多个用户)
前端防抖处理按钮点击
七、完整示例流程
1. 用户A访问用户B的个人主页
2. 前端发送请求获取关注状态:
GET /api/follow/status?current_user_id=1&target_user_id=2
3. 后端返回状态:
{
"isFollowing": false,
"isFollowedBy": true,
"isMutual": false
}
4. 前端根据状态渲染按钮:
显示"关注"按钮(用户A未关注用户B)
显示"已关注"按钮(用户A已关注用户B)
显示"互相关注"状态(双方已互关)
5. 用户点击按钮,前端发送操作请求
6. 后端处理后返回结果,前端更新UI和关注数
八、扩展功能建议
关注提醒系统:当有新粉丝时通知用户
共同关注推荐:基于共同关注的好友推荐
关注分组管理:将关注用户分类管理
关注时间线:按关注时间排序展示
隐私设置:控制谁可以关注自己
关键词:PHP开发、互关注功能、数据库设计、RESTful API、前端交互、关注状态管理、性能优化、安全措施
简介:本文详细介绍了使用PHP开发互关注功能的完整实现步骤,包括数据库设计、后端API实现、前端交互逻辑以及安全与性能优化。从关注/取消关注操作到状态查询,提供了可落地的代码示例和最佳实践,帮助开发者快速构建稳定的社交关注系统。