Multi-tiered Comment Replies: Display and Storage

前端 未结 5 1808
夕颜
夕颜 2021-02-02 04:18

So I\'m trying to create a comment system in which you can reply to comments that are already replies (allowing you to create theoretically infinite threads of replies). I want

5条回答
  •  南方客
    南方客 (楼主)
    2021-02-02 05:21

    You might find this method helpful which involves a single call to a non-recursive stored procedure.

    Full script can be found here : http://pastie.org/1259785

    Hope it helps :)

    Example stored procedure call:

    call comments_hier(1);
    

    Example php script:

    query(sprintf("call comments_hier(%d)", 3));
    
    while($row = $result->fetch_assoc()){
        ...
    }
    
    $result->close();
    $conn->close();
    ?>
    

    SQL script:

    drop table if exists comments;
    create table comments
    (
    comment_id int unsigned not null auto_increment primary key,
    subject varchar(255) not null,
    parent_comment_id int unsigned null,
    key (parent_comment_id)
    )engine = innodb;
    
    
    insert into comments (subject, parent_comment_id) values
    ('Comment 1',null), 
       ('Comment 1-1',1), 
       ('Comment 1-2',1), 
          ('Comment 1-2-1',3), 
          ('Comment 1-2-2',3), 
            ('Comment 1-2-2-1',5), 
            ('Comment 1-2-2-2',5), 
               ('Comment 1-2-2-2-1',7);
    
    
    delimiter ;
    
    drop procedure if exists comments_hier;
    
    delimiter #
    
    create procedure comments_hier
    (
    in p_comment_id int unsigned
    )
    begin
    
    declare v_done tinyint unsigned default 0;
    declare v_depth smallint unsigned default 0;
    
    create temporary table hier(
     parent_comment_id smallint unsigned, 
     comment_id smallint unsigned, 
     depth smallint unsigned default 0
    )engine = memory;
    
    insert into hier select parent_comment_id, comment_id, v_depth from comments where comment_id = p_comment_id;
    
    /* http://dev.mysql.com/doc/refman/5.0/en/temporary-table-problems.html */
    
    create temporary table tmp engine=memory select * from hier;
    
    while not v_done do
    
        if exists( select 1 from comments c inner join hier on c.parent_comment_id = hier.comment_id and hier.depth = v_depth) then
    
            insert into hier 
                select c.parent_comment_id, c.comment_id, v_depth + 1 from comments c
                inner join tmp on c.parent_comment_id = tmp.comment_id and tmp.depth = v_depth;
    
            set v_depth = v_depth + 1;          
    
            truncate table tmp;
            insert into tmp select * from hier where depth = v_depth;
    
        else
            set v_done = 1;
        end if;
    
    end while;
    
    select 
     c.comment_id,
     c.subject,
     p.comment_id as parent_comment_id,
     p.subject as parent_subject,
     hier.depth
    from 
     hier
    inner join comments c on hier.comment_id = c.comment_id
    left outer join comments p on hier.parent_comment_id = p.comment_id
    order by
     hier.depth, hier.comment_id;
    
    drop temporary table if exists hier;
    drop temporary table if exists tmp;
    
    end #
    
    delimiter ;
    
    
    call comments_hier(1);
    
    call comments_hier(5);
    

提交回复
热议问题