2009-08-11 6 views
9

나는 꽤 오랫동안이 문제에 대해 생각 해왔다. 데이터베이스의 댓글에 답글을 추가 할 방법이 필요하지만 어떻게 진행해야할지 모르겠다.댓글 및 댓글 응답을위한 mysql 구조

이 내 현재 (많은 말을하지 않지만 그 시작) 테이블을 언급 :

SELECT c.id, c.comment, c.user_id, u.username, u.photo 
FROM (comments c) 
JOIN users u ON c.user_id = u.id 
WHERE c.topic_id = 9 

하나의 옵션이를 생성하는 것입니다 :

CREATE TABLE IF NOT EXISTS `comments` (
    `id` int(12) NOT NULL AUTO_INCREMENT, 
    `comment` text, 
    `user_id` int(12) DEFAULT NULL, 
    `topic_id` int(12) NOT NULL, 
    `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`), 
    KEY `user_id` (`user_id`), 
    KEY `topic_id` (`topic_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=27 ; 

여기에 내 현재 쿼리입니다 "comment_replies"라는 새 표가 있지만 확실하지 않은 경우 하나의 쿼리에서 모든 댓글과 댓글을 선택할 수 있고 "reply"라는 새 열을 추가하면 어떻게 정렬할지 잘 모르겠습니다. 각 답글에 대해 각 의견을 얻으십시오.

이 문제를 해결하는 방법에 대한 조언을 받고 싶습니다.

편집 : 아래 1 코멘트에서 배열의이 종류에 parent_comment_id 결과를 추가하는 방법에 대한 답변이 개 답변에 따라

: 나는 그것을 작업이 배열을 처리하는 방법을

array(2) { 
    [0]=> 
    object(stdClass)#17 (7) { 
    ["id"]=> 
    string(2) "26" 
    ["comment"]=> 
    string(36) "adding a comment from the admin page" 
    ["user_id"]=> 
    string(2) "16" 
    ["ts"]=> 
    string(10) "1249869350" 
    ["username"]=> 
    string(5) "Admin" 
    ["photo"]=> 
    string(13) "gravatar2.png" 
    ["reply"]=> 
    string(23) "There is no admin page!" 
    } 
    [1]=> 
    object(stdClass)#18 (7) { 
    ["id"]=> 
    string(2) "26" 
    ["comment"]=> 
    string(36) "adding a comment from the admin page" 
    ["user_id"]=> 
    string(2) "16" 
    ["ts"]=> 
    string(10) "1249869350" 
    ["username"]=> 
    string(5) "Admin" 
    ["photo"]=> 
    string(13) "gravatar2.png" 
    ["reply"]=> 
    string(13) "Yes there is!" 
    } 
} 

, 답변에서 댓글을 분리 할 수 ​​있습니까?

답변

3

데이터베이스에 parent_id 열을 추가하기로 결정하고 대신 답장에 참여하기 전에 모든 의견을 한 번에 선택하여 나중에 메모를 정렬하고 서버로 답장했습니다. - 측 코드를 heres 쿼리 : 모든 응답이 코멘트 배열의 내부 배열로 추가 할 수 있도록

SELECT c.*, u.username, u.photo 
FROM (comments c) 
JOIN users u ON c.user_id = u.id 
WHERE c.topic_id = 9 
ORDER BY c.id ASC 

지금 그래서 기본적으로는 다차원 배열을 반환, 아래 함수에 쿼리 결과를 전달합니다.

function sort_comments($ar) 
{ 
    $comments = array(); 
    foreach($ar as $item) 
    { 
     if(is_null($item['parent_id'])) $comments[] = $item; 
     else 
     { 
      $parent_array = array_search_key($item['parent_id'],$comments,'id'); 
      if($parent_array !== false) $comments[$parent_array]['replies'][] = $item; 
     } 
    } 
    return $comments; 
} 
+3

'array_search_key' 함수는 무엇입니까? PHP 표준 라이브러리 함수가 아닙니다. – HorusKol

+0

페이지 매김은 어떻게 작동합니까? – Mrusful

+0

여기서 array_search_key 함수는 무엇입니까 ?? 그것은 PHP에 존재합니까? –

1

댓글 답글은 부모 comment_id가있는 댓글입니다. 주석 테이블에 comment_id를 필드로 추가하십시오. 네가 얻을 수있는 것은 나무와 같은 구조이다.

전체 의견 트리를 검색하려면 중첩 된 집합 (https://wiki.htc.lan/Hierarchy_model)을 사용하는 것이 가장 좋습니다. 그러나 그것은보다 복잡한 해결책입니다.

다음은 MySQL의에서 좀 더 정보입니다 : http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

3

는 귀하의 의견 테이블에 parent_comment_id 열을 추가합니다. 옵션으로 설정하십시오. 쿼리 할 때 모든 하위 주석을 각 부모와 조인 할 수 있습니다. 약간의 선택적인 비정규 화 (약간의 중복성)로서, 자식 주석에 대해서도 topic_id을 설정할 수 있습니다. 모든 주석은 주 주석 스레드에 표시하고 그렇지 않은 경우 더 작은 ajax 요청을 통해).

프리젠 테이션을 빌드하고 결과를 memcached (또는 플랫 파일 또는 메모리 ... 캐싱 중이지만 ...)로 설정하면 설정됩니다.

4

사람들이 답장에 응답 할 수있게하려면 (예 : 온라인 메시지 포럼에 표시되는 것과 같은 응답 구조를 가짐), 옵션으로 parent_comment_id 필드를 주석 테이블에 추가합니다 .

테이블이 같은 것이 모두의 의견과 응답을 보여주는이

`CREATE TABLE IF NOT EXISTS `comments` (
    `id` int(12) NOT NULL AUTO_INCREMENT, 
    `parent_comment_id` int(12) NULL, 
    `comment` text, 
    `user_id` int(12) DEFAULT NULL, 
    `topic_id` int(12) NOT NULL, 
    `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`), 
    KEY `user_id` (`user_id`), 
    KEY `topic_id` (`topic_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=27 ;` 

질문과 같습니다

SELECT c.id, c.comment, r.comment as reply, c.user_id, u.username, u.photo 
FROM (comments c) 
JOIN users u ON c.user_id = u.id 
LEFT JOIN comments r ON c.id = r.parent_comment_id 
WHERE c.topic_id = 9 

참고 그러나이 질의와 응답은 또한뿐만 아니라 표시 것이라고 'reply'열뿐만 아니라 'comment'열에도 각각 0 개 이상의 응답이있는 추가 행이 있습니다.

댓글에 답글을 작성한 사용자의 사용자 이름을 표시하려면 사용자 테이블에 두 번 가입해야합니다 (처음으로 댓글을 게시 한 사용자의 경우, 다시 답글을 작성한 사용자의 경우). 대답 사용자의 사용자 이름을 표시하려면이 쿼리를보십시오 : 당신은 워드 프레스로 작업 parent_comment_id는하지만이 경우, 이상적인 솔루션을했을 추가하는 것처럼

SELECT c.id, c.comment, c.user_id, u.username, u.photo, r.comment as reply, r.user_id as reply_user_id, 
u2.username as reply_username, u2.photo as reply_photo 
FROM (comment c) 
JOIN users u ON c.user_id = u.id 
LEFT JOIN comments r ON c.id = r.parent_comment_id 
JOIN users u2 ON r.user_id = u2.id 
WHERE c.topic_id = 9 
+0

parent_comment_id를 추가하고 쿼리를 변경했지만 다음에 수행 할 작업을 잘 모르겠습니다. 두 개의 응답으로 1 개의 주석이 있고, 두 개의 주석이 생성되며, 두 개의 주석이 모두 같지만 다른 응답을 가질 것이며 두 개의 응답 모두 첫 번째 주석 사용자 이름을 갖게됩니다. 예제로 내 메인 포스트를 편집했습니다. – Dennis

+0

나는 위의 원래 쿼리를 편집하여 코멘트에 답한 사용자의 사용자 이름과 사진을 보여줍니다. – flayto

+0

좋아 보이지만 여전히 한 주석에 대해 하나 이상의 응답이있는 중복 된 주석 값을 출력합니다. 응답에서 주석을 분리하기 위해 서버 측 코드로 결과 배열을 변경해야합니까? – Dennis

1

보인다.

첫째, 나는 WordPress 기본 테이블을 수정하는 것이 좋은 생각이라고 생각하지 않습니다. 둘째, Wordpress 업데이트로 해결할 복잡한 코드로 끝납니다.

최저

당신이 자신의 솔루션을 만들려면, 내가 코멘트 응답에 대한 다른 테이블을 만들 말을 아직 Intense Comments

같은 플러그인을 사용합니다. 가) 새 테이블이

`CREATE TABLE IF NOT EXISTS `comment_replies` (
    `id` int(12) NOT NULL AUTO_INCREMENT, 
    `parent_comment_id` int(12) NULL, 
    `comment` text, 
    `user_id` int(12) DEFAULT NULL, 
    `topic_id` int(12) NOT NULL, 
    `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`), 
    KEY `user_id` (`user_id`), 
    KEY `topic_id` (`topic_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 

나 같을 것이다) 당신은 당신이

같은 응답을 얻을 수 귀하의 의견 루프 내에서 지금은) 그들에게이 방법

$comment_ids = array_map('intval', array_keys($comments)); 
sort($comment_ids); 
$comments_id_list = join(',', $comment_ids); 

$query = "SELECT c.id, c.comment, c.user_id, u.username, u.photo 
FROM (comment_replies c) 
JOIN users u ON c.user_id = u.id 
WHERE c.parent_comment_id IN ($comments_id_list)" 

$replies = $wpdb->get_results($query); 
$replies_by_parent = array(); 

foreach (array_keys($replies) as $i) {   
    $replies_by_parent [$replies[$i]->id] = array(); 
} 
foreach (array_keys($replies) as $i) {   
    $replies_by_parent [$replies[$i]->id][] =& $replies[$i]; 
} 

C를 가져올 것

foreach ( $replies_by_parent [$parent_id] as $reply) {    
     echo $reply->comment; 
    } 
+0

나는 wordpress를 사용하지 않지만 해결책은 상당히 좋아 보인다. 나는 그것이 나를 위해 그것의 최적인지보기 위해 더 많이보아야한다. – Dennis

1

이 모든 것이 좋지만 100 만 개가 넘는 행이 포함되어 있다면 어떨까요? 일부 의견은 수십만 개의 행으로 구분 될 수 있습니다. 이러한 쿼리는 어떻게 수행됩니까?

+0

사실, 그렇지만 지금 당장은 그렇게할만한 데이터가 있다면 가장 좋은 방법은 두 개의 다른 테이블로 구분하는 것입니다. – Dennis