【问题标题】:Trouble building nested list of threaded messages in PHP在 PHP 中构建嵌套的线程消息列表时遇到问题
【发布时间】:2022-05-13 23:22:27
【问题描述】:

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

我有两个表:Threads 和 Posts,我在此处对其进行了简化以供演示。

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

+----+-----------------+---------------------+
| 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 |
+----+-----------------+---------------------+

Posts 表基本上是这样的:

+----+------+-----+----------------------------------+
| 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         |
+----+------+-----+----------------------------------+

其中每个帖子都与另一个表上的线程相关,并且通过解析 parentID 列在此表中确定父/子关系。以“0”为父节点的帖子是根节点。

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

  1. 获取所有线程,按最新排序
  2. 对于每个线程,通过匹配 thread_ids 获取所有帖子,按 parent_id 排序
  3. 对于每个线程,以某种方式(递归?)遍历这个帖子列表并创建一个 PHP 有序列表,适当缩进显示父母和孩子之间的关系。

可悲的是,在过去的 3 天里,这是最后一步让我陷入了彻底的停顿。以“线程 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

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

添加以澄清意图:在生产中,每个帖子都是一个链接, 打开以显示消息的全文。回应将是 附加用户和日期的相同“线程名称”。因此,例如, 胎面可能会显示“登录时发现错误”和我的回复(第一个孩子) 将显示为:“在登录期间发现错误 - Chris Conlee 19/07/01 09:10”我 意识到上面的例子在没有上下文的情况下看起来很奇怪。

老实说,我没有任何运行良好的代码可以在这里发布。有一次,我有一个递归例程,它只遍历最左边的腿,然后跳过对帖子 5 的第二个响应。

在另一点上,我有一个例程显示所有节点一式三份,并且缩进一直无法正常工作。

我深表歉意,因为这似乎应该是一个非常简单的练习,但我只是让自己陷入困境,试图了解它的递归性质,再加上多线程等。如果有人可以抛出我的生命线将不胜感激。

【问题讨论】:

  • 尝试 recursiveiteratoriterator 并使用它的 getDepth 方法来计算缩进...
  • Posts 中的数据库设计对您没有任何帮助。不过,我对嵌套列表的最后一个示例感到困惑,什么是帖子 6?为什么要按时间倒序显示回复?
  • @parttimeturtle 由于我处于设计和测试阶段,我很乐意考虑 DB 设计的替代方案。我的示例使用了不是最直观的父子名称。如果您参考原始表格示例,示例中的所有 4 个帖子都与“线程 5”相关,对“帖子”的响应指的是父帖子的 ID。它们按照它们的方式排序,因为我首先想要最近的帖子(在树的结构内,即:维护线程,并保留父/子关系。)完整的树将包含所有 5 个线程。例如,我只展示了 1 个。
  • @parttimeturtle 顺便说一句,在生产中,线程会更具描述性,例如:“在登录部分发现错误”,用户(或我自己)可以回复。我的想法是,所有回复都将具有相同的线程名称,并附加用户名和发布日期。所以我的回复(第一个孩子)可能是:“在登录部分发现一个错误 - Chris Conlee 于 2019-07-01 09:00:00”,当点击时,完整的回复会出现。只是为了澄清意图。我知道这个例子在没有上下文的情况下很奇怪。

标签: php listview recursion treeview adjacency-list


【解决方案1】:

好吧,我终于放慢了脚步,逐个元素地迭代并弄清楚了。

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

[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>";
        }
    }
}

递归遍历树,返回类似的结果:


(来源:post-tools.com)

【讨论】:

    猜你喜欢
    • 2014-08-31
    • 1970-01-01
    • 2016-01-16
    • 1970-01-01
    • 1970-01-01
    • 2021-10-09
    • 1970-01-01
    • 2013-02-16
    • 2014-05-07
    相关资源
    最近更新 更多