点赞功能需求:用户能点赞,能取消赞,同时能查看赞了该条状态的所有人,可能还需要提醒发该条状态的人谁谁谁赞了你。
web端实现:显示点赞数,当有用户赞了该状态,则点赞数+1等。
本文从点赞功能的数据库设计说起,一步步到各个功能的基本实现方法。
数据库设计
首先是2张表,t_user表与t_tatus表,分别表示用户表与状态表。Ps:这个点赞功能是需要登录的。(如果是不需要登录就能点赞,最好还需要多个字段或新表来记录用户IP,防止重复点赞)
那么关键是点赞功能怎么在数据库中表现出来。
刚开始我觉得直接在t_tatus表中加一个like字段,当有用户点了赞,直接拼个user_id组成的字符串,用逗号隔开, 形如1,2,3,4写入即可。麻烦的是每次写入新的id都要重新拼一次字符串,取消赞也要操作一次字符串,每次取得赞的所有人也要处理字符串,每次计算赞的人数也要拆一次字符串。
当是这种写法也不是没好处,节省空间,不用新表,数据库开销小。无非计算字符串来来回回比较浪费时间。
为了以后查询好处理一点,我的实现还是新建了一张t_like表(有新方案的小伙伴可以评论留言讨论),结构如下。
表t_user结构:
1 2 3 4 5 6 7 8
| CREATE TABLE `t_user` ( `userID` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(255) NOT NULL UNIQUE, `nickname` varchar(255) DEFAULT NULL , `pwd` varchar(255) NOT NULL , `phoneno` varchar(64) DEFAULT NULL , PRIMARY KEY (`userID`) )
|
表t_tatus结构:
1 2 3 4 5 6
| CREATE TABLE `t_tatus` ( `statusID` int(11) NOT NULL AUTO_INCREMENT, `userID` int(11) NOT NULL , `statusContent` varchar(255) NULL DEFAULT NULL , PRIMARY KEY (`statusID`) )
|
表t_like结构:(双主键)
1 2 3 4 5 6
| CREATE TABLE `t_like` ( `statusID` int(11) NOT NULL , `userID` int(11) NOT NULL , `createTime` varchar(45) NULL DEFAULT NULL , PRIMARY KEY (`statusID`,`userID`) )
|
服务器端
服务器端主要做的就是点赞时在t_like表中插入一条数据,取消赞时找到t_like表中的对应数据删除,很easy。PS:可能还需要统计赞的个数并返回,sql语句count()一下。
文件名like.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| require_once('common.php'); $userID = $_GET['userID']; $statusID = $_GET['statusID']; $getMethod = $_GET['getMethod']; $do = $_GET['do']; if (!isset($userID) || !isset($statusID)) { return Response::show(401, '参数不合法'); eixt(); } try { $connect = Db::getInstance()->connect(); } catch (Exception $e) { return Response::show(403, '数据库连接失败'); } function do_like($connect,$getMethod,$statusID,$userID){ $nowTime = date('Y-m-d H:i:s', time()); $sql = "INSERT INTO t_like(statusID,userID,createTime) VALUES ($statusID,$userID,'$nowTime')"; $result = mysql_query($sql, $connect); if ($result) { if ($getMethod == "web") { echo "Y"; } } else { return Response::show(402, '点赞失败'); } } function do_unlike($connect,$getMethod,$statusID,$userID){ $sql = "delete from t_like where statusID=$statusID and userID=$userID"; $result = mysql_query($sql, $connect); if ($result) { if ($getMethod == "web") { echo "N"; } } else { return Response::show(403, '取消赞失败'); } } if($do == "auto"){ $sql = "SELECT createTime FROM t_like WHERE statusID=$statusID and userID=$userID"; $query = mysql_query($sql,$connect); if ($query) { if ($rs = mysql_fetch_array($query)) { do_unlike($connect,$getMethod,$statusID,$userID); }else { do_like($connect,$getMethod,$statusID,$userID); } } else { return Response::show(401, '查询失败'); } }else if ($do == "like") { do_like($connect,$getMethod); } else if ($do == "unlike") { do_unlike($connect,$getMethod,$statusID,$userID); } else { return Response::show(401, '参数不合法'); }
|
common.php文件中包含了一些封装的返回信息,数据库连接封装。
web端
Ajax实现web端点赞
1
| <button id = "zanName" onclick="demo()">赞</button>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| <script> ajax点击更新赞的数目 function demo() { var xmlhttp; if (window.XMLHttpRequest) { xmlhttp = new XMLHttpRequest(); } else { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.open("GET", "like.php?userID=1&statusID=1&getMethod=web&do=auto", true); xmlhttp.send(); xmlhttp.onreadystatechange = function () { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { var isLike = xmlhttp.responseText; if(isLike == 'Y'){ document.getElementById("zanName").innerHTML = "已赞"; }else if(isLike == 'N'){ document.getElementById("zanName").innerHTML = "赞"; } } } } </script>
|
通过获取服务器返回的Y,或者N来自动判断是否点过赞。点过赞则显示已赞,再次点击则取消赞。
扩展
可以用客户端Cookie记录用户是否点赞,也可以用Session判断用户是否登录,并记录用户是否点赞。然后再对数据库进行操作。
结语
潜在问题
因为实际需求中点赞数量可能很庞大,多用户+多status时更是惊人。使得这张t_like表可能变得巨大,且没必要,那么如何解决?
我的优化思路
定期清理t_like表中的数据,如用户删除了status的;时间过去久远的status可以只记录点赞的总条数,把对应的t_like中数据删除。
功能不尽完善,实际需求时很多细节功能要复杂很多,本文仅提供一些思路,不贴完整代码。