评论系统如下图所示,具有登录系统,注册系统,站点管理,贴子管理,游客系统,评论管理,评论发表,评论删除,评论回复,评论点赞等等。这是一个简单的模型,作为三方评论系统的基本结构。
用户数据表在上一篇已经介绍过了,这里不再重复介绍。注册使用的基本信息为用户名,密码,邮箱。与其他数据表关联时,不使用自增id,而是生成唯一id,这样在数据库迁移时也可以把数据很好的对应上,同样的对每一条评论数据,也要单独生成uuid。另外,为方便用户,我们提供了游客账号,稍后讲解。相关代码如下:
public function doRegisterComment()
{
$user_validate = new \app\index\validate\CommentUser;
if(!$user_validate->check($this->request->param('', null, 'urldecode'))){
dump($user_validate->getError());
}
$jsoncallback = $this->get('jsoncallback');
$account = $this->get('account');
$newPwd = $this->get('newPwd');
$confirmPwd = $this->get('confirmPwd');
$email = $this->get('email');
$securityCode = $this->get('securityCode');
$admin = $this->get('admin1234');
if(Db::name('user')->where('account', $account)->find()){
return $this->create_res([
"info"=>"用户名[$account]已存在"
]);
}
$uniqid = uniqid();
//create user, usertype:0 normal member, 1 admin, 2 guest
$id = Db::name('user')->insertGetId([
'uuid'=>$uniqid,
'user_type' => $admin ? 1 : 0,
'account'=>$account,
'password'=>md5($confirmPwd),
'email'=>$email,
'regtime'=>time(),
'lastlogintime'=>time(),
'islogin'=>1,
'head'=>''
]);
//注册成功后
$second = md5($email);
$third = md5(time());
cookie('cookieUserLoginEntityInfos', $uniqid.'_'.$second.'_'.$third);
$user_data = [
'id'=>$id,
'uuid'=>$uniqid,
'account'=>$account,
'password'=>md5($confirmPwd),
'email'=>$email,
'user_type'=>$admin ? 1 : 0,
'head'=>'',
'lastlogintime'=>time()
];
cache($uniqid.'_'.$second.'_'.$third, json_encode($user_data), 24*3600);
Db::name('user')->where('id', $id)->update(['cache_key'=>$uniqid.'_'.$second.'_'.$third]);
return $this->create_res(['info'=>'保存成功']);
}
用户填写完表单之后,后台验证用户账号,检查授权信息(接入评论系统必要步骤),验证成功之后,对客户端要设置登录凭证(cookie)。对于用户数据操作,为减少数据库读写,在登录之后,需要把用户数据提取到缓存。否则,数据读写会成为网站负载的瓶颈。代码如下:
public function doLoginComment(){
if(!$this->check_callback()){
return $this->return_info("invalid parameter");
}
$account = $this->get('account');
$password = $this->get('pwd');
$securityCode = $this->get('securityCode');
$captcha = new Captcha(config('app.varify_config'));
if(!$captcha->check($securityCode)){
return $this->create_res(['info'=>'验证码输入错误']);
}
$user_entity = Db::name('user')->where('account', $account)->find();
if(!$user_entity){
return $this->create_res([
'info'=>'用户名或密码错误'
]);
}
if($user_entity['password'] != md5($password)){
return $this->create_res([
'info'=>'用户名或密码错误'
]);
}
$uniqid = $user_entity['uuid'];
$id = $user_entity['id'];
$second = md5($user_entity['email']);
$third = md5(time());
if($user_entity['cache_key']){
cache($user_entity['cache_key'], null);
}
cookie('cookieUserLoginEntityInfos', $uniqid.'_'.$second.'_'.$third);
$user_data = [
'id'=>$id,
'uuid'=>$uniqid,
'account'=>$user_entity['account'],
'password'=>$user_entity['password'],
'email'=>$user_entity['email'],
'user_type'=>$user_entity['user_type'],
'head'=>$user_entity['head']
];
cache($uniqid.'_'.$second.'_'.$third, json_encode($user_data), 24*3600);
Db::name('user')->where('id', $id)->update(['cache_key'=>$uniqid.'_'.$second.'_'.$third]);
return $this->create_res(['info'=>'登录成功']);
}
这部分不是本篇讨论的重点,不再详述。
需要注意的是用户必须登录之后才可以对评论进行操作,而且每个用户对每条评论只能操作一次,实现方式有以下几种:
if(!$this->check_callback()){
return $this->return_info("invalid request");
}
if(!$this->check_login()){
return $this->return_info("need login");
}
$comment_id = $this->get('commentUuid');
if(!$comment_id){
return $this->return_info("commentid not found");
}
$user_data = json_decode(cache(cookie('cookieUserLoginEntityInfos')), true);
$key = $user_data['uuid'].'_'.$comment_id;
if(cache($key) == 1){
return $this->create_res(["info"=>"您已经操作过了哦"]);
}
cache($key, 1, 0);//this will produce many keys, can be improved by only store userid->data
Db::name('comment')->where('uuid', $comment_id)->inc('top');
return $this->create_res([
"info"=>"顶成功"
]);
评论的发表与评论的回复是同一个处理过程,因为回复评论在我们的系统中,也做成了一条正常的评论。评论回复系统,在数据存储上使用了回复评论列表的形式,可以根据id的先后顺序实现评论回复的级别,因为回复只能针对一条评论进行。
if(!$this->check_login()){
return $this->return_info("need login");
}
$config = Db::name('config')->where('option_name', 'save_switch')->find();
if($config && !$config['option_value']){
return $this->return_info("评论系统已经关闭");
}
$siteKey = $this->post('siteKey');
$threadKey = $this->post('threadKey');
$commentContent = $this->post('commentContent');
$user_uuid = $this->post('doIframeCommentUuid');
$commentUuid = $this->post('commentUuid');
$comment_uuid = get_unique_id();
$site = Db::name('site')->where('site_key', $siteKey)->find();
$thread = Db::name('thread')->where('thread_key', $threadKey)->find();
$site_id = 0;
$thread_id = 0;
if(!$site){
if(config('varify_site')){
return $this->return_info('invalid parameter, site or thread not regist1');
}else{
$site_id = $this->addSite($siteKey);
}
}else{
$site_id = $site['id'];
}
if(!$thread){
if(config('verify_site')){
return $this->return_info('invalid parameter, site or thread not regist2');
}else{
$thread_id = $this->addThread($threadKey);
}
}else{
$thread_id = $thread['id'];
}
$user_data = $this->getLoginUserData();
if(!$user_data){
return $this->return_info("login data error, pls contact manager");
}
$ret = false;
if($commentUuid)
{
//评论回复
$comment = Db::name('comment')->where('uuid', $commentUuid)->find();
if(!$comment){
return $this->create_res(['info'=>'评论不存在']);
}else{
$reply_list = $comment['reply_uuids'];
if($reply_list)
$reply_list = $reply_list . ',' . $comment['uuid'];
else
$reply_list = $comment['uuid'];
$ret = Db::name("comment")->insert([
'uuid' => $comment_uuid,
'content' => $commentContent,
'posttime' => floor(microtime(true)*1000),
'site_id' => $site_id,
'thread_id' => $thread_id,
'user_uuid' => $user_data['uuid'],
'reply_uuids' => $reply_list
]);
}
}
else
{
$ret = Db::name("comment")->insert([
'uuid' => $comment_uuid,
'content' => $commentContent,
'posttime' => floor(microtime(true)*1000),
'site_id' => $site_id,
'thread_id' => $thread_id,
'user_uuid' => $user_data['uuid'],
'is_top' => ($user_data['user_type'] == 1 ? 1 : 0)
]);
}
if($user_data['user_type'] == 1){
$key = $this->select_top_key . $site_id . $thread_id;
cache($key, null);
$key = $this->select_top_cnt . $site_id . $thread_id;
cache($key, null);
}else{
//clear comment caches
$key = $this->select_key . $site_id . $thread_id;
cache($key, null);
$page_idx = 1;
$order_type = [1,2,3];
foreach($order_type as $type){
$page_idx = 1;
while(true){
$cahce_key_check = "?".$this->select_key.$site_id.$thread_id.$type.$page_idx;
$cache_key = $this->select_key.$site_id.$thread_id.$type.$page_idx;
if(cache($cahce_key_check, '')){
cache($cache_key, null);
$page_idx += 1;
}else{
break;
}
}
}
$key = $this->count_key . $site_id . $thread_id;
cache($key, null);
}
if($ret){
return $this->create_res([
'info'=>'发布成功'
]);
}
return $this->create_res([
'info'=>'数据操作错误'
]);
这两个部分放一起是因为用户系统可以是统一的,用户分为管理员,注册用户与游客(也是普通用户),对于注册用户或游客只可以删除自己发过的评论,而对于管理员可以删除任何评论,包括自己的评论。这部分实现比较简单,验证权限之后操作就可以了。
评论系统就介绍到这里,欢迎在下方评论。