设计图

/wiki/wiki/评论一表三模型.JPG

Mysql

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
--  Table structure for `discuss`
-- ----------------------------
DROP TABLE IF EXISTS `discuss`;
CREATE TABLE `discuss` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `user_id` int(10) NOT NULL,
  `tieno` int(10) NOT NULL,
  `tieid` int(10) NOT NULL,
  `th` int(10) DEFAULT NULL COMMENT '位于本贴子的第几楼',
  `re_th` int(10) DEFAULT '0' COMMENT '一级留言为0, 回复为目标评论id',
  `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_bin COMMENT '具体内容, 支持表情',
  `deleted` int(1) NOT NULL DEFAULT '0' COMMENT '默认没有删除为0 , 已删为1',
  `create_time` bigint(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4;

-- ----------------------------
--  Records of `discuss`
-- ----------------------------
BEGIN;
INSERT INTO `discuss` VALUES ('1', '1', '2', '1660', '1', '0', '我是1660的sofa', '0', '1479103933'), ('2', '2', '2', '1660', '2', '0', '我是1660的板凳', '0', '1479103954'), ('3', '4', '2', '1660', '3', '0', '我是1660的3楼', '0', '1479103974'), ('4', '1', '2', '1660', '4', '3', '你好3喽', '0', '1479104037'), ('5', '4', '2', '1660', '5', '3', '你也好3喽', '0', '1479104065'), ('6', '4', '2', '1660', '6', '5', '6=>5', '0', '1479104093'), ('7', '4', '2', '1660', '7', '5', '7-5', '0', '1479104119'), ('8', '4', '2', '1660', '8', '0', '#8', '0', '1479104132');
COMMIT;

SET FOREIGN_KEY_CHECKS = 1;


PHP

<?php
class Discuss_model extends CI_Model
{
    public static $subno = 4;

    public function __construct()
    {
        parent::__construct();
    }


    /**
     * 新插入一条评论(留言/回复)
     * @param $content
     * @param $user_id
     * @param $tieno
     * @param $tieid
     * @param int $reply 默认0为留言;否则为要回复的id
     * @return CI_DB_active_record|CI_DB_result
     */
    public function add($content, $user_id, $tieno, $tieid, $re_th = 0)
    {
        $data = array();
        $data['user_id'] = intval($user_id);
        $data['tieno'] = intval($tieno);

        //本类型下的最近一次评论时间
        $ans0 = $this->db
            ->select("create_time")
            ->where($data)
            ->order_by('create_time DESC')
            ->get('discuss');
        //相同用户相同板块下, 5s 内只允许发一条
        if ($ans0->row() !== null) {
            $last_ct = $ans0->row()->create_time;
            if (time() - $last_ct < 5) {
                return [204, "嘴太碎了,歇会儿再发~"];
            }
        }

        $data['content'] = htmlentities(mb_substr($content, 0, 140));//每条内容最多140个字符
        $data['tieid'] = intval($tieid);
        $data['deleted'] = 0;
        $data['create_time'] = time();
        $data['re_th'] = intval($re_th);
        $ans1 = $this->db->insert('discuss', $data);

        if ($ans1) {
            $insert_id = $this->db->insert_id();
            $ans2 = $this->db
                ->query(
                    "SELECT COUNT(id) AS count_id FROM discuss WHERE tieno = ? AND tieid = ? AND id < ?",
                    array($tieno, $tieid, $insert_id)
                );
            $ans3 = $this->db
                ->where(array('id' => $insert_id))
                ->update('discuss', array('th' => intval($ans2->row()->count_id) + 1));

            if (!$ans3) {
                return [207, '系统错误.'];
            }

            return [100, '评论成功.'];

        } else {
            return [207, '评论保持失败.'];
        }
    }


    /**
     * 删除自己的评论
     * @param $discuss_id
     * @param $user_id
     * @return CI_DB_active_record|CI_DB_result
     */
    public function del($discuss_id, $user_id)
    {
        $row = $this->db->get_where('discuss', array('id' => intval($discuss_id)))->row();
        if (!$row) {
            return [202, "评论不存在."];
        }

        if ($row->deleted != 0) {
            return [202, "评论已删除."];
        }

        if ($row->user_id != $user_id) {
            return [206, "非法操作,权限不足."];
        }

        $ans = $this->db
            ->where('id', intval($discuss_id))
            ->update('discuss', array('deleted' => 1));

        if (!$ans) {
            return [207, '系统错误.'];
        }

        return [100, '删除成功.'];
    }


    /**
     * 该本体下挂载的评论数
     * @param $tieno
     * @param $tieid
     * @return int
     */
    private function discussions_count($tieno, $tieid)
    {
        $row1 = $this->db
            ->select("count(id) as count")
            ->where('tieno', intval($tieno))
            ->where('tieid', intval($tieid))
            ->get('discuss')
            ->row();
        return intval($row1->count);
    }


    /**
     * 评论列表1(单层模型)
     * @param $tieno
     * @param $tieid
     * @param int $page
     * @param int $count
     * @return array [$total, $results];
     */
    public function discussions($tieno, $tieid, $page = 0, $count = 10)
    {
        $total = $this->discussions_count($tieno, $tieid);
        if ($total == 0) {
            //空, 无评论挂载
            return [$total, array()];
        }

        $results = $this->db
            ->select('discuss.*, users.face, users.nick')
            ->from('discuss')
            ->join('users', 'users.id = discuss.user_id')
            ->where('tieno', $tieno)
            ->where('tieid', $tieid)
            ->order_by("discuss.create_time ASC, discuss.id ASC")
            ->limit($count, $page * $count)
            ->get()
            ->result_array();

        return [$total, $results];
    }


    /**
     * 评论列表2(盖楼模式)
     * @param $tieno
     * @param $tieid
     * @param int $page
     * @param int $count
     * @return array
     */
    public function discussions2($tieno, $tieid, $page = 0, $count = 10)
    {
        $total = $this->discussions_count($tieno, $tieid);
        $raw_list = $this->db
            ->select('discuss.*,users.face,users.nick')
            ->from('discuss')
            ->join('users', 'discuss.user_id = users.id')
            ->where('tieno', $tieno)
            ->where('tieid', $tieid)
            ->order_by("discuss.create_time ASC, discuss.id ASC")
            ->limit($count, $page * $count)
            ->get()
            ->result_array();

        $data = [];
        foreach ($raw_list as $child) {
            $data[] = $this->build_family_tree($child);
        }

        return [$total, $data];
    }


    /**
     * 构建祖先树
     * for discussion2.
     * 祖先放首位,孩子依次往后
     * @param $child
     * @param array $family_tree
     * @return array
     */
    private function build_family_tree($child, $family_tree = [])
    {
        //将father插到首位
        array_unshift($family_tree, $child);

        if ($child['re_th'] == 0) {
            return $family_tree;
        }
        $father = $this->db
            ->select('discuss.*,users.face,users.nick')
            ->from('discuss')
            ->join('users', 'discuss.user_id = users.id')
            ->where('tieno', $child['tieno'])
            ->where('tieid', $child['tieid'])
            ->where('th', $child['re_th'])
            ->get()
            ->row_array();
        return $this->build_family_tree($father, $family_tree);
    }


    /**
     * 根据 评论id数组 获取评论内容
     * @param $discuss_id_arr
     * @return array key即discuss_id
     */
    public function get_dis_info($discuss_id_arr)
    {
        if (!$discuss_id_arr) {
            return array();
        }

        $IDs = array();
        foreach ($discuss_id_arr as $dis_id) {
            $id = intval($dis_id);
            if ($id > 0) {
                $IDs[] = $id;
            }
        }

        $result_array = $this->db
            ->select("discuss.*, users.face,users.nick")
            ->from('discuss')
            ->join('users', 'users.id = discuss.user_id')
            ->where_in('discuss.id', $discuss_id_arr)
            ->get()
            ->result_array();

        $data = array();
        foreach ($result_array as $per_dis) {
            $data[intval($per_dis['id'])] = $per_dis;
        }

        return $data;
    }


    /**
     * 评论列表3(递进层级模型)
     * @param $tieno
     * @param $tieid
     * @param int $page
     * @param int $count
     * @return array
     */
    public function discussions3($tieno, $tieid, $page = 0, $count = 10)
    {
        //所有一级留言
        $fathers = $this->db
            ->select("discuss.*, users.face, users.nick")
            ->from("discuss")
            ->join("users", "discuss.user_id = users.id")
            ->where("tieno", $tieno)
            ->where("tieid", $tieid)
            ->where("re_th", 0)
            ->limit($count, $page * $count)
            ->get()
            ->result_array();
        $data = array();
        foreach ($fathers as $father) {
            $data[] = $this->buildDiscussTree($father);
        }

        return $data;
    }

    /**
     * 递归创建评论家族树,由祖先开始向后DFS
     * for discussion3 (递进层级模型)
     */
    public function buildDiscussTree($father)
    {
        $family_tree = [];
        //下一级id列表
        $children = $this->getSubDiscussions($father);

        //$children 为空数组时不会进入foreach,即退出条件
        foreach ($children as $child) {
            $family_tree[] = $this->buildDiscussTree($child);
        }
        return [$father, $family_tree];
    }


    /**
     * 所有一级孩子对象
     * for discussion3 (递进层级模型)
     * @param $father
     * @return mixed
     */
    private function getSubDiscussions($father)
    {
        return
            $this->db
                ->select("discuss.*, users.face, users.nick")
                ->from('discuss')
                ->join('users', 'discuss.user_id = users.id')
                ->where('tieno', $father['tieno'])
                ->where('tieid', $father['tieid'])
                ->where('re_th', $father['th'])
                ->order_by("discuss.create_time ASC, discuss.id ASC")
                ->get()
                ->result_array();
    }

}