在ThinkPHP 6.1中实现点赞功能,结合Redis作为缓存和数据存储,可以有效地提高性能和并发处理能力。以下是一个基本的设计思路和代码实现示例。
设计思路
-
数据结构设计:
- 使用Redis的
Hash
结构来存储每个内容的点赞数,键名为like:content_id
,字段为用户ID,值为点赞状态(1表示已点赞,0表示未点赞)。 - 使用Redis的
Set
结构来存储每个用户的点赞记录,键名为user:user_id:likes
,值为内容ID。
- 使用Redis的
-
点赞操作:
- 用户点赞时,首先检查用户是否已经点赞过该内容。
- 如果未点赞,则在
Hash
中增加点赞数,并在Set
中记录用户的点赞。 - 如果已点赞,则取消点赞,减少点赞数,并从
Set
中移除记录。
-
获取点赞数:
- 直接从
Hash
中获取某个内容的点赞数。
- 直接从
-
获取用户点赞记录:
- 从
Set
中获取某个用户的点赞记录。
- 从
代码实现
首先,确保你已经安装了predis/predis
库来操作Redis。
bash
composer require predis/predis
然后,在ThinkPHP 6.1中编写代码:
php
<?php
namespace app\api\controller;
use app\BaseController;
use think\facade\Cache;
class Like extends BaseController
{
// 点赞或取消点赞
public function like()
{
$param = $this->request->POST();
$contentId = $param['contentId'];
$userId = $param['userId'];
$redis = Cache::store('redis')->handler();
$likeKey = "like:{$contentId}";
$userLikeKey = "user:{$userId}:likes";
// 检查用户是否已经点赞
if ($redis->hget($likeKey, $userId)) {
// 取消点赞
$redis->hset($likeKey, $userId, 0);
$redis->srem($userLikeKey, $contentId);
$redis->hincrby($likeKey, 'count', -1);
} else {
// 点赞
$redis->hset($likeKey, $userId, 1);
$redis->sadd($userLikeKey, $contentId);
$redis->hincrby($likeKey, 'count', 1);
}
return json(['code' => 200, 'msg' => '操作成功']);
}
// 获取内容的点赞数
public function getLikeCount()
{
$param = $this->request->get();
$contentId = $param['contentId'];
$redis = Cache::store('redis')->handler();
$likeKey = "like:{$contentId}";
$count = $redis->hget($likeKey, 'count');
return json(['code' => 200, 'data' => ['count' => !$count ? 0:$count]]);
}
// 获取用户的点赞记录
public function getUserLikes($userId)
{
$redis = Cache::store('redis')->handler();
$userLikeKey = "user:{$userId}:likes";
$likes = $redis->smembers($userLikeKey);
return json(['code' => 200, 'data' => ['likes' => $likes]]);
}
}
配置Redis
在config/cache.php
中配置Redis:
dart
return [
'default' => 'redis',
'stores' => [
'redis' => [
'type' => 'redis',
'host' => '127.0.0.1',
'port' => 6379,
'password' => '',
'select' => 0,
'timeout' => 0,
'persistent' => false,
],
],
];
路由配置
在route/route.php
中配置路由:
css
use think\facade\Route;
Route::post('like/like/', 'Like/like');
Route::get('like/getLikeCount/', 'Like/getLikeCount');
Route::get('like/getUserLikes/:userId', 'Like/getUserLikes');
前端页面设计
-
页面结构:
- 展示内容的标题和点赞数。
- 提供一个点赞按钮,点击后可以点赞或取消点赞。
- 展示用户的点赞记录。
-
样式设计:
- 使用CSS来美化页面,使按钮和内容看起来更吸引人。
- 使用动画效果来增强用户体验。
-
交互设计:
- 使用JavaScript的
fetch
API来与后端接口进行交互。 - 动态更新点赞数和点赞按钮的状态。
- 使用JavaScript的
代码实现
HTML
xml
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>点赞功能示例</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f9;
color: #333;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
}
.container {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
text-align: center;
}
h1 {
margin-bottom: 20px;
}
#likeButton {
background-color: #007bff;
color: white;
border: none;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
transition: background-color 0.3s ease;
}
#likeButton:hover {
background-color: #0056b3;
}
ul {
list-style-type: none;
padding: 0;
}
ul li {
background: #f8f9fa;
margin: 5px 0;
padding: 10px;
border-radius: 5px;
}
</style>
</head>
<body>
<div class="container">
<h1>内容标题</h1>
<p>点赞数: <span id="likeCount">0</span></p>
<button id="likeButton">点赞</button>
<h2>我的点赞记录</h2>
<ul id="userLikes"></ul>
</div>
<script>
document.addEventListener('DOMContentLoaded', function () {
const contentId = 1; // 假设内容ID为1
const userId = 1; // 假设用户ID为1
const likeButton = document.getElementById('likeButton');
const likeCount = document.getElementById('likeCount');
const userLikes = document.getElementById('userLikes');
// 获取点赞数
function fetchLikeCount() {
const params = new URLSearchParams({
contentId:contentId
})
fetch(`api/like/getLikeCount?${params.toString()}`)
.then(response => response.json())
.then(data => {
likeCount.textContent = data.data.count;
likeButton.textContent = data.data.count > 0 ? '取消点赞' : '点赞';
});
}
// 获取用户点赞记录
function fetchUserLikes() {
const params = new URLSearchParams({
userId:userId
})
fetch(`api/like/getUserLikes?${params.toString()}`)
.then(response => response.json())
.then(data => {
userLikes.innerHTML = data.data.likes.map(like => `<li>内容ID: ${like}</li>`).join('');
});
}
// 点赞或取消点赞
likeButton.addEventListener('click', function () {
const headers = new Headers()
headers.append('content-type', 'application/json')
fetch(`api/like/like`, { method: 'POST',headers,body: JSON.stringify({ contentId: contentId, userId: userId }) })
.then(response => response.json())
.then(data => {
if (data.code === 200) {
fetchLikeCount();
fetchUserLikes();
}
});
});
// 初始化页面
fetchLikeCount();
fetchUserLikes();
});
</script>
</body>
</html>
总结
通过上述设计思路和代码实现,你可以在ThinkPHP 6.1中结合Redis实现一个高效的点赞功能。Redis的高性能和原子操作确保了点赞功能的并发处理能力和数据一致性。