在 PHP 中构建线程消息的嵌套列表时遇到问题

Trouble building nested list of threaded messages in PHP

我正在构建一个非常简单的线程消息系统,主要供我网站的用户在我扩展网站功能时与我和彼此交流错误和问题。但是,我没有运气为每个线程创建一个正确的嵌套列表。

我有两个 tables:主题和帖子,我在这里进行了简化以供展示。

线程 table 大致如此,按最近修改的线程排序:

+----+-----------------+---------------------+
| id | thName          | thModified          |
+----+-----------------+---------------------+
| 5  | Thread Number 5 | 2019-06-29 20:54:59 |
+----+-----------------+---------------------+
| 4  | Thread Number 4 | 2019-06-29 20:45:22 |
+----+-----------------+---------------------+
| 3  | Thread Number 3 | 2019-06-29 20:44:20 |
+----+-----------------+---------------------+
| 2  | Thread Number 2 | 2019-06-29 20:43:00 |
+----+-----------------+---------------------+
| 1  | Thread Number 1 | 2019-06-29 20:39:25 |
+----+-----------------+---------------------+

帖子table大体是这样的:

+----+------+-----+----------------------------------+
| Id | thID | pID | postMessage                      |
+----+------+-----+----------------------------------+
| 1  | 1    | 0   | First message of thread number 1 |
+----+------+-----+----------------------------------+
| 2  | 2    | 0   | First message of thread number 2 |
+----+------+-----+----------------------------------+
| 3  | 3    | 0   | First message of thread number 3 |
+----+------+-----+----------------------------------+
| 4  | 4    | 0   | First message of thread number 4 |
+----+------+-----+----------------------------------+
| 5  | 5    | 0   | First message of thread number 5 |
+----+------+-----+----------------------------------+
| 6  | 5    | 5   | First response to post 5         |
+----+------+-----+----------------------------------+
| 7  | 5    | 5   | Second response to post 5        |
+----+------+-----+----------------------------------+
| 8  | 5    | 6   | First response to post 6         |
+----+------+-----+----------------------------------+
| 9  | 1    | 1   | First response to post 1         |
+----+------+-----+----------------------------------+

其中每个 post 都与另一个 table 上的线程相关,并且 parent/child 关系在此 table 中通过解析 parent 来确定标识栏。以“0”作为 parent 的帖子是根节点。

我的基本攻击计划是这样的:

  1. 获取所有线程,按最新排序
  2. 对于每个线程,通过匹配thread_ids获得所有posts,按parent_id
  3. 排序
  4. 对于每个线程,以某种方式(递归地?)遍历这个 post 列表并创建一个 PHP 有序列表,正确缩进显示 parent 和 children.

遗憾的是,这是过去 3 天让我完全停滞不前的最后一步。以 "Thread 5" 为例,在第 2 步之后,我有一个如下所示的数组:

    [0] => Array
        (
            [post_id] => 5
            [thread_id] => 5
            [parent_id] => 0
            [user_id] => 9
            [post_message] => First message of thread number 5
            [post_created] => 2019-06-29 20:54:59
            [thread_title] => Thread Number 5
        )

    [1] => Array
        (
            [post_id] => 6
            [thread_id] => 5
            [parent_id] => 5
            [user_id] => 9
            [post_message] => First response to post 5
            [post_created] => 2019-06-29 21:39:00
            [thread_title] => Thread Number 5
        )

    [2] => Array
        (
            [post_id] => 7
            [thread_id] => 5
            [parent_id] => 5
            [user_id] => 9
            [post_message] => Second response to post 5
            [post_created] => 2019-06-29 21:52:00
            [thread_title] => Thread Number 5
        )

    [3] => Array
        (
            [post_id] => 8
            [thread_id] => 5
            [parent_id] => 6
            [user_id] => 0
            [post_message] => First response to post 6
            [post_created] => 2019-06-29 21:55:00
            [thread_title] => Thread Number 5
        )

我想从该数组生成一个嵌套列表,如下所示:

Thread Number 5 - First message of thread number 5
    Thread Number 5 - Second response to post 5
    Thread Number 5 - First response to post 5
        Thread Number 5 - First response to post 6

请注意,响应按 post 日期排序(最近的排在最前面),当然对于后续的线程,我希望缩进再次回到零位置。

Added to clarify intent: in production each post would be a link that opens to display the full text of the message. Responses would be the same "thread name" with user and date appended. So, for example, the tread might read "Found bug during login" and my response (1st child) would read: "Found bug during login - Chris Conlee 19/07/01 09:10" I realized the example above seems weird without context.

老实说,我没有任何运行良好的代码可以 post 放在这里。有一次我有一个递归例程,它只遍历 left-most 段,然后跳过对 post 5.

的第二个响应

在另一点上,我有一个例程,它一式两份地显示所有节点,但缩进从未正常工作。

我深表歉意,因为它看起来应该是一个非常简单的练习,但我只是让自己陷入困境,试图让我的头脑围绕它的递归性质,再加上多线程等。如果有人可以给我一条救生索,我将不胜感激。

好吧,我终于放慢了速度,逐个元素地迭代并弄明白了。

相对于给定的线程提供一组帖子,例如:

[0] => Array
        (
            [post_id] => 5
            [thread_id] => 5
            [parent_id] => 0
            [user_id] => 9
            [post_message] => First message of thread number 5
            [post_created] => 2019-06-29 20:54:59
            [thread_title] => Thread Number 5
        )

    [1] => Array
        (
            [post_id] => 6
            [thread_id] => 5
            [parent_id] => 5
            [user_id] => 9
            [post_message] => First response to post 5
            [post_created] => 2019-06-29 21:39:00
            [thread_title] => Thread Number 5
        )

    [2] => Array
        (
            [post_id] => 7
            [thread_id] => 5
            [parent_id] => 5
            [user_id] => 9
            [post_message] => Second response to post 5
            [post_created] => 2019-06-29 21:52:00
            [thread_title] => Thread Number 5
        )

    [3] => Array
        (
            [post_id] => 8
            [thread_id] => 5
            [parent_id] => 6
            [user_id] => 0
            [post_message] => First response to post 6
            [post_created] => 2019-06-29 21:55:00
            [thread_title] => Thread Number 5
        )

进入如下方法:

public function buildForum($postsToThread, &$forum, $parent_id = 0) {
    foreach ($postsToThread as $post) {
        $time = strtotime($post['post_created']);
        $tmpCurrentAuthorName = $this->getPostAuthor($post['user_id']);
        $tmpCurrentThreadTitle = $post['thread_title'];
        $tmpCurrentPostDate = date("M d, Y g:i A", $time);
        if ($post['parent_id'] == $parent_id) {
            $forum .= "<ol><li><a href='/freetools/forumViewPost/" .$post['post_id'] . "'>" . $tmpCurrentThreadTitle .= " by " . $tmpCurrentAuthorName . "</a> on " . $tmpCurrentPostDate . "</li>";
            $parent_id = $post['post_id'];
            $this->buildForum($postsToThread, $forum, $parent_id);
            $parent_id = $post['parent_id'];
            $forum .= "</ol>";
        }
    }
}

递归遍历树,returns结果类似于:


(来源:post-tools.com