질문Q #8136
ci 답변형 게시판입니다.
개발사랑2013-02-06 14:14:42
제가 이해한 로직이 맞는지도 점검할겸 글을 올립니다.
잘못되었으면 말씀해주세요.
일전에 다른분이 올려주신 소스에 답글과 spac_editor 등을 추가했습니다.
아 코드이그나이터를 이용해서 만들었습니다.
액티브레코드도 부분 부분 사용했습니다.
먼저 4가지의 필드가 필요합니다.
no = int로서 순차적으로 증가되는 각 필드의 고유값
list_number = 실제 정렬된 순서를 지정하는 필드
depth = 답글의 깊이를 정함
parent = 원본글의 no 값(저도 다른곳의 포스트를 보고 만들었는데 실제로서는 이 필드는 거의 필요가 없는듯 합니다.)
일단 리스트 출력상에서는 list_number asc로 출력합니다.
새글 기입시
등록된 글이 없이 처음일시 list_number에 무조건 1을 기입하도록 합니다.
새글등록시 이미 등록된 글에 가장 최신 list_number에 -1을 해 list_number를 등록하게 되어 있습니다.
이때 로직상 -1 이거나 0으로 되면 1로 세팅해서 업데이트 시킵니다.
그 이외에는 새 글 기입시 등록된 글보다 no값이 작은 경우 무조건 list_number를 +1시키고
새글은 등록된 글 중 가장 작은 list_number 값을 추출해 그 값에 -1을 해 입력시킵니다.
이때 parent_id는 원본글의 값 depth는 1로 세팅합니다.
답변글 등록시
parent_id는 원본글의 값 depth는 원본글의 depth에서 +1를 해 처리합니다.
list_number는 원본글의 list_number보다 큰 경우 전부 +1을 해주고 새글의 list_number는 원본글의 list_number에서
+1을 해 처리합니다. 그러면 원본글의 list_number보다 큰 경우와 원본글 사이에 숫자가 하나남는 상황이 생기고
그 숫자로 답글이 처리되어 list_number asc를 하면 답글이 원본글의 바로 밑에 출력됩니다.
아래는 소스입니다. 저도 정리한다고 남기는글인데 두서 없네요 혹시 의문사항이 생기시면 답글 바랍니다.
새글 기입시 (주석참고)
$this->title = $_POST['title'];
$this->memo = $_POST['memo'];
$this->name = $_POST['name'];
$this->img01 = $_FILES['userfile']['name'];
$this->ip = $_SERVER["REMOTE_ADDR"];
$this->date = date("Y-m-d H:i:s",time());
/*
$this->db->select_max('thread');
$result_set = $this->db->get('board');
$thread_array = $result_set->result_array();
print_r($thread_array);
exit;
*/
$this->db->insert('board', $this);
// 핵심은 list_number 필드에 있다.
// 그런데 데이터 많으면 부하걸리겠다. list_number를 계속 업데이트 해주어야 한다.
// 삽입된 원글의 아이디값을 추출한다.
$id = $this->db->insert_id();
// 원글보다 먼저 등록된 글들의 list_number를 다 1씩 증가시킨다.
// 왜냐하면 답글이 아니고 신규글이기 때문에 제일 위에 정렬된다.
$this->db->query("update board set list_number=list_number+1 where no <".$id);
// 가장작은 리스트 넘버의 값을 추출해서 거기에 -1를 한 값이 최종글의 번호가 된다.
// 게시판 리스트 정렬시에는 가장 작은 값이 위에 오게된다.
$res = $this->db->query("select min(list_number) as list_number_min from board");
$board_array = $res->result_array();
$num_rows = $res->num_rows();
$set_list_number = $board_array[0]['list_number_min'] - 1;
if($set_list_number == -1 || $set_list_number == 0)
{
$set_list_number = 1;
}
$data = array(
'list_number' => $set_list_number,
'depth' => 1,
'parent' => $id
);
$this->db->where('no', $id);
$this->db->update('board', $data);
답글 기입시(주석참고)
$this->title = $_POST['title'];
$this->memo = $_POST['memo'];
$this->name = $_POST['name'];
$this->img01 = $_FILES['userfile']['name'];
$this->ip = $_SERVER["REMOTE_ADDR"];
$this->date = date("Y-m-d H:i:s",time());
/*
$this->db->select_max('thread');
$result_set = $this->db->get('board');
$thread_array = $result_set->result_array();
print_r($thread_array);
exit;
*/
$this->db->insert('board', $this);
$id = $this->db->insert_id();
// 답글의 원본글의 정보를 추출한다.
$this->db->select('*');
$this->db->from('board');
$this->db->where('no', $_POST['no']);
$query = $this->db->get();
$sel_board_array = $query->result();
$depth = $sel_board_array[0]->depth + 1;
// 원본글의 list_number보다 큰 먼저 정렬된글들의 list_number를 전부더해 답글의 밑에 보이도록 한다.
// 이때 list_number가 작은글들은 업데이트 되지 않는다 왜냐하면 list_number가 큰 글들을 전부 +1 업데이트 시키고
// 원본글과 +1 시킨 글 사이에 답글의 list_number가 위치할것이기 때문이다.
$this->db->query("update board set list_number=list_number+1 where list_number >".$sel_board_array[0]->list_number);
$set_list_number = $sel_board_array[0]->list_number + 1;
if($set_list_number == -1 || $set_list_number == 0)
{
$set_list_number = 1;
}
$data = array(
'list_number' => $set_list_number,
'depth' => $depth,
'parent' => $sel_board_array[0]->no
);
$this->db->where('no', $id);
$this->db->update('board', $data);
// $res_set = $sel_board_array[0]->res + 1;
// $rev_set = $sel_board_array[0]->rev + 1;
// $this->db->set('res', 'res+1');
// $this->db->where('ref', $_POST['ref']);
// $this->db->where('res >', $sel_board_array[0]->res);
// $this->db->update('board');
// $this->db->query("update board set res=res+1 where ref ='".$_POST['ref']."' and res > ".$sel_board_array[0]->res);
// $this->db->query("update board set ref=".$_POST['no'].", rev = ".$rev_set.", res=".$res_set." where no = ".$id);
// $this->db->query();
/*
$data = array(
'ref' => $_POST['no'],
'res' => $res_set,
'rev' => $rev_set
);
$this->db->where('ref', $id);
$this->db->where('res >', $sel_board_array[0]->res);
$this->db->update('board', $data);
*/
주석에 보니 list_number 를 계속 업데이트 하는데 주석에 쓰신 것처럼
데이터가 많이지면 느려질 수 밖에 없습니다.
업데이트 하지 않는 로직들도 있으니 그걸 적용해서 만드시는게 좋을 것 같습니다.
로직은 머리 아프긴 합니다. 전에 게시판 답글 무한depth, 덧글 무한depth 구현하느라
머리 아팠던 기억이 나네요.