PHP如何循环多个注释级别

时间:2014-06-26 10:29:35

标签: php mysql loops nested

我的数据库结构目前看起来像这样(对于评论系统):

但是,我完全失去了如何循环使用这些数据,尤其是嵌套注释/不同级别。

目前,我遍历数据并显示所有level 0条评论,并且对于每个0级评论,循环查找并找到相应的level 1条评论。但是,最多可以有10个级别,并且按照我的方式循环使用所有10个级别,我觉得效率非常低。

replyTo列引用它作为回复的评论的ID。如果数字为0,则表示评论不是回复。因此,对于上面的表格,例如,我想用PHP循环它以显示某些东西(从最近到最旧):

hello
    what do you want
    test
        Good!
test
This is a page!
    test

2 个答案:

答案 0 :(得分:0)

示例php脚本(假设传递给函数的数据库连接类)。

<?php

post_replies($db, 0, 0);

function post_replies($db, $cnt=0, $parent_id=0)
{
    $messages = array();
    $sql = "SELECT id, message
            FROM some_table
            WHERE replyTo = ".(int)$parent_id."
            ORDER BY date";
    $results = $db->query($sql);
    while($row = $db->fetch_assoc())
    {
        $messages[] = $row;
    }
    foreach($messages AS $message)
    {
        echo str_repeat("\t", $cnt).$message['message'];
        post_replies($db, $cnt + 1, $message['id'])
    }
}

?>

这可以通过调整来避免对没有回复的邮件进行进一步查询: -

<?php

post_replies($db, 0, 0);

function post_replies($db, $cnt=0, $parent_id=0)
{
    $messages = array();
    $sql = "SELECT a.id, a.message, COUNT(b.id) AS child_count
            FROM some_table a
            LEFT OUTER JOIN some_table b
            ON a.id = b.parent_id
            WHERE a.replyTo = ".(int)$parent_id."
            GROUP BY a.id, a.message
            ORDER BY a.date";
    $results = $db->query($sql);
    while($row = $db->fetch_assoc())
    {
        $messages[] = $row;
    }
    foreach($messages AS $message)
    {
        echo str_repeat("\t", $cnt).$message['message'];
        if ($message['child_count'] > 0)
        {
            post_replies($db, $cnt + 1, $message['id'])
        }
    }
}

?>

修改

想过这个,决定玩一玩。由于你有一个最大级别的数量,这可能是一个冗长的SQL。

这可以通过获取replyTo为0的所有消息,然后使用replyTo为0和子记录的所有消息进行UNIONing。并对盛大的儿童记录等做同样的事。

在排序上略微捏造,这会以正确的顺序恢复: -

SELECT a.date AS aDate, a.id AS aId, 
        b0.date AS b0Date, b0.id AS b0Id, 
        b1.date AS b1Date, b1.id AS b1Id, 
        b2.date AS b2Date, b2.id AS b2Id, 
        b3.date AS b3Date, b3.id AS b3Id, 
        b4.date AS b4Date, b4.id AS b4Id, 
        b5.date AS b5Date, b5.id AS b5Id, 
        b6.date AS b6Date, b6.id AS b6Id, 
        b7.date AS b7Date, b7.id AS b7Id, 
        b8.date AS b8Date, b8.id AS b8Id, 
        CONCAT(REPEAT('-', 9), b8.message)
FROM some_table a
INNER JOIN some_table b0 ON a.id = b0.replyTo
INNER JOIN some_table b1 ON b0.id = b1.replyTo
INNER JOIN some_table b2 ON b1.id = b2.replyTo
INNER JOIN some_table b3 ON b2.id = b3.replyTo
INNER JOIN some_table b4 ON b3.id = b4.replyTo
INNER JOIN some_table b5 ON b4.id = b5.replyTo
INNER JOIN some_table b6 ON b5.id = b6.replyTo
INNER JOIN some_table b7 ON b6.id = b7.replyTo
INNER JOIN some_table b8 ON b7.id = b8.replyTo
WHERE a.replyTo = 0
UNION ALL
SELECT a.date AS aDate, a.id AS aId, 
        b0.date AS b0Date, b0.id AS b0Id, 
        b1.date AS b1Date, b1.id AS b1Id, 
        b2.date AS b2Date, b2.id AS b2Id, 
        b3.date AS b3Date, b3.id AS b3Id, 
        b4.date AS b4Date, b4.id AS b4Id, 
        b5.date AS b5Date, b5.id AS b5Id, 
        b6.date AS b6Date, b6.id AS b6Id, 
        b7.date AS b7Date, b7.id AS b7Id, 
        NULL AS b8Date, NULL AS b8Id, 
        CONCAT(REPEAT('-', 8), b7.message)
FROM some_table a
INNER JOIN some_table b0 ON a.id = b0.replyTo
INNER JOIN some_table b1 ON b0.id = b1.replyTo
INNER JOIN some_table b2 ON b1.id = b2.replyTo
INNER JOIN some_table b3 ON b2.id = b3.replyTo
INNER JOIN some_table b4 ON b3.id = b4.replyTo
INNER JOIN some_table b5 ON b4.id = b5.replyTo
INNER JOIN some_table b6 ON b5.id = b6.replyTo
INNER JOIN some_table b7 ON b6.id = b7.replyTo
WHERE a.replyTo = 0
UNION ALL
SELECT a.date AS aDate, a.id AS aId, 
        b0.date AS b0Date, b0.id AS b0Id, 
        b1.date AS b1Date, b1.id AS b1Id, 
        b2.date AS b2Date, b2.id AS b2Id, 
        b3.date AS b3Date, b3.id AS b3Id, 
        b4.date AS b4Date, b4.id AS b4Id, 
        b5.date AS b5Date, b5.id AS b5Id, 
        b6.date AS b6Date, b6.id AS b6Id, 
        NULL AS b7Date, NULL AS b7Id, 
        NULL AS b8Date, NULL AS b8Id, 
        CONCAT(REPEAT('-', 7), b6.message)
FROM some_table a
INNER JOIN some_table b0 ON a.id = b0.replyTo
INNER JOIN some_table b1 ON b0.id = b1.replyTo
INNER JOIN some_table b2 ON b1.id = b2.replyTo
INNER JOIN some_table b3 ON b2.id = b3.replyTo
INNER JOIN some_table b4 ON b3.id = b4.replyTo
INNER JOIN some_table b5 ON b4.id = b5.replyTo
INNER JOIN some_table b6 ON b5.id = b6.replyTo
WHERE a.replyTo = 0
UNION ALL
SELECT a.date AS aDate, a.id AS aId, 
        b0.date AS b0Date, b0.id AS b0Id, 
        b1.date AS b1Date, b1.id AS b1Id, 
        b2.date AS b2Date, b2.id AS b2Id, 
        b3.date AS b3Date, b3.id AS b3Id, 
        b4.date AS b4Date, b4.id AS b4Id, 
        b5.date AS b5Date, b5.id AS b5Id, 
        NULL AS b6Date, NULL AS b6Id, 
        NULL AS b7Date, NULL AS b7Id, 
        NULL AS b8Date, NULL AS b8Id, 
        CONCAT(REPEAT('-', 6), b5.message)
FROM some_table a
INNER JOIN some_table b0 ON a.id = b0.replyTo
INNER JOIN some_table b1 ON b0.id = b1.replyTo
INNER JOIN some_table b2 ON b1.id = b2.replyTo
INNER JOIN some_table b3 ON b2.id = b3.replyTo
INNER JOIN some_table b4 ON b3.id = b4.replyTo
INNER JOIN some_table b5 ON b4.id = b5.replyTo
WHERE a.replyTo = 0
UNION ALL
SELECT a.date AS aDate, a.id AS aId, 
        b0.date AS b0Date, b0.id AS b0Id, 
        b1.date AS b1Date, b1.id AS b1Id, 
        b2.date AS b2Date, b2.id AS b2Id, 
        b3.date AS b3Date, b3.id AS b3Id, 
        b4.date AS b4Date, b4.id AS b4Id, 
        NULL AS b5Date, NULL AS b5Id, 
        NULL AS b6Date, NULL AS b6Id, 
        NULL AS b7Date, NULL AS b7Id, 
        NULL AS b8Date, NULL AS b8Id, 
        CONCAT(REPEAT('-', 5), b4.message)
FROM some_table a
INNER JOIN some_table b0 ON a.id = b0.replyTo
INNER JOIN some_table b1 ON b0.id = b1.replyTo
INNER JOIN some_table b2 ON b1.id = b2.replyTo
INNER JOIN some_table b3 ON b2.id = b3.replyTo
INNER JOIN some_table b4 ON b3.id = b4.replyTo
WHERE a.replyTo = 0
UNION ALL
SELECT a.date AS aDate, a.id AS aId, 
        b0.date AS b0Date, b0.id AS b0Id, 
        b1.date AS b1Date, b1.id AS b1Id, 
        b2.date AS b2Date, b2.id AS b2Id, 
        b3.date AS b3Date, b3.id AS b3Id, 
        NULL AS b4Date, NULL AS b4Id, 
        NULL AS b5Date, NULL AS b5Id, 
        NULL AS b6Date, NULL AS b6Id, 
        NULL AS b7Date, NULL AS b7Id, 
        NULL AS b8Date, NULL AS b8Id, 
        CONCAT(REPEAT('-', 4), b3.message)
FROM some_table a
INNER JOIN some_table b0 ON a.id = b0.replyTo
INNER JOIN some_table b1 ON b0.id = b1.replyTo
INNER JOIN some_table b2 ON b1.id = b2.replyTo
INNER JOIN some_table b3 ON b2.id = b3.replyTo
WHERE a.replyTo = 0
UNION ALL
SELECT a.date AS aDate, a.id AS aId, 
        b0.date AS b0Date, b0.id AS b0Id, 
        b1.date AS b1Date, b1.id AS b1Id, 
        b2.date AS b2Date, b2.id AS b2Id, 
        NULL AS b3Date, NULL AS b3Id, 
        NULL AS b4Date, NULL AS b4Id, 
        NULL AS b5Date, NULL AS b5Id, 
        NULL AS b6Date, NULL AS b6Id, 
        NULL AS b7Date, NULL AS b7Id, 
        NULL AS b8Date, NULL AS b8Id, 
        CONCAT(REPEAT('-', 3), b2.message)
FROM some_table a
INNER JOIN some_table b0 ON a.id = b0.replyTo
INNER JOIN some_table b1 ON b0.id = b1.replyTo
INNER JOIN some_table b2 ON b1.id = b2.replyTo
WHERE a.replyTo = 0
UNION ALL
SELECT a.date AS aDate, a.id AS aId, 
        b0.date AS b0Date, b0.id AS b0Id, 
        b1.date AS b1Date, b1.id AS b1Id, 
        NULL AS b2Date, NULL AS b2Id, 
        NULL AS b3Date, NULL AS b3Id, 
        NULL AS b4Date, NULL AS b4Id, 
        NULL AS b5Date, NULL AS b5Id, 
        NULL AS b6Date, NULL AS b6Id, 
        NULL AS b7Date, NULL AS b7Id, 
        NULL AS b8Date, NULL AS b8Id, 
        CONCAT(REPEAT('-', 2), b1.message)
FROM some_table a
INNER JOIN some_table b0 ON a.id = b0.replyTo
INNER JOIN some_table b1 ON b0.id = b1.replyTo
WHERE a.replyTo = 0
UNION ALL
SELECT a.date AS aDate, a.id AS aId, 
        b0.date AS b0Date, b0.id AS b0Id, 
        NULL AS b1Date, NULL AS b1Id, 
        NULL AS b2Date, NULL AS b2Id, 
        NULL AS b3Date, NULL AS b3Id, 
        NULL AS b4Date, NULL AS b4Id, 
        NULL AS b5Date, NULL AS b5Id, 
        NULL AS b6Date, NULL AS b6Id, 
        NULL AS b7Date, NULL AS b7Id, 
        NULL AS b8Date, NULL AS b8Id, 
        CONCAT(REPEAT('-', 1), b0.message)
FROM some_table a
INNER JOIN some_table b0 ON a.id = b0.replyTo
WHERE a.replyTo = 0
UNION ALL
SELECT a.date AS aDate, a.id AS aId, 
        NULL AS b0Date, NULL AS b0Id, 
        NULL AS b1Date, NULL AS b1Id, 
        NULL AS b2Date, NULL AS b2Id, 
        NULL AS b3Date, NULL AS b3Id, 
        NULL AS b4Date, NULL AS b4Id, 
        NULL AS b5Date, NULL AS b5Id, 
        NULL AS b6Date, NULL AS b6Id, 
        NULL AS b7Date, NULL AS b7Id, 
        NULL AS b8Date, NULL AS b8Id, 
        a.message
FROM some_table a
WHERE a.replyTo = 0
ORDER BY aDate DESC, aID, 
        IFNULL(b0Date, '2099-12-31') DESC, b0Id, 
        IFNULL(b1Date, '2099-12-31') DESC, b1Id, 
        IFNULL(b2Date, '2099-12-31') DESC, b2Id, 
        IFNULL(b3Date, '2099-12-31') DESC, b3Id, 
        IFNULL(b4Date, '2099-12-31') DESC, b4Id, 
        IFNULL(b5Date, '2099-12-31') DESC, b5Id, 
        IFNULL(b6Date, '2099-12-31') DESC, b6Id, 
        IFNULL(b7Date, '2099-12-31') DESC, b7Id, 
        IFNULL(b8Date, '2099-12-31') DESC, b8Id

SQL小提琴: -

http://www.sqlfiddle.com/#!2/775405/12

答案 1 :(得分:0)

你必须选择:

很多查询

您只需在循环中选择所需的注释:

<?php

function displayCommentsRecursive($stmnt, $replyTo = 0) {
    // Select the top comments first
    $stmnt->execute(array(0));
    $result = $stmnt->fetchAll();

    foreach($result as $res) {
        // display comment
        echo $res->user , ': ' , $res->text;

        echo displayCommentsRecursive($res->ID);
    }
}

$stmntGetComments = $pdo->prepare("
    SELECT ID, user, text
    FROM comment
    WHERE replyTo = ?
");

displayCommentsRecursive($stmntGetComments);

多次迭代

您只需触发一次查询,然后从&#34;评论池中选择您需要的评论&#34;:

<?php

function displayCommentsRecursive(array $comments, $replyTo = 0) {
    foreach($result as $res) {
        if($replyTo != $res->replyTo)
            continue;

        // display comment
        echo $res->user , ': ' , $res->text;

        echo displayCommentsRecursive($comments, $res->ID);
    }
}

$stmntGetComments = $pdo->prepare("
    SELECT ID, user, text, replyTo
    FROM comment
");

// Select all comments at once
$stmntGetComments->execute(array(0));
$comments = $stmntGetComments->fetchAll();

displayCommentsRecursive($comments);