【问题标题】:Laravel recursion - finding the "last post"Laravel 递归 - 找到“最后一个帖子”
【发布时间】:2016-05-10 19:06:00
【问题描述】:

我有一个论坛系统,其中包含许多类别,其中包含许多帖子。

因此,对于给定的论坛,我应该能够找出特定论坛的最后一篇帖子。一个论坛可以有许多子论坛(又名子论坛)。我只能完成其中的一部分。

表格演示:

| id | parent_id | name              | is_category |
|----|-----------|-------------------|-------------|
| 1  | 0         | Suggestions       | 1           |
| 2  | 1         | site suggestions  | 0           |
| 3  | 1         | forum suggestions | 0           |
| 4  | 2         | bugs              | 0           |

这是我的代码:

public function lastPost()
{
    foreach ($this->threads()->orderBy('updated_at')->get() as $thread) {
        $post = $thread->lastPost();
    }
    if ($this->hasSubforum()) {
        foreach ($this->subforums as $subforum) {
            $post = $subforum->lastPost();
        }
    }
    return $post;
}

如您所见,lastPost() 被调用,直到论坛没有更多子论坛。我正在从一个子论坛的最新线程中获得最后一篇文章。到目前为止,一切都很好。但是,最后一个帖子将是子论坛所在的顺序。因此,如果最后一个帖子在倒数第二个子论坛中,则返回最后一个子论坛的最后一个帖子,因为最后一个论坛在递归中最后返回。

我该如何解决这个问题?

谢谢!

【问题讨论】:

  • 检查日期并仅在日期较新的情况下设置$post(或者甚至帖子的id - 假设有一个 - 假设它是连续的)?
  • 您可能可以在 $this->threads()...etc 集合中使用最后一种方法,对吧? laravel.com/docs/5.1/collections#method-last

标签: php laravel recursion


【解决方案1】:

我认为您应该对这个问题采取不同的方法。当您拥有大量用户时,您尝试做的方式会使您的数据库崩溃。如果您知道这棵树有多深,那么像这样进行大量“左连接”会更好地提高性能:

select  d3.parent_id as parent3_id,
        d2.parent_id as parent2_id,
        d1.parent_id as parent_id,
        d1.id as product_id,
        d1.name
from      demo d1
left join demo d2 on d2.id = d1.parent_id 
left join demo d3 on d3.id = d2.parent_id 
... join as many as you think it will have data ...
where  $this->id in (d1.parent_id, 
               d2.parent_id, 
               d3.parent_id) 
order by 1, 2, 3;

在这种情况下,您将只执行 1 次查询,在您的情况下,您将执行 n+1 次查询,如果使用延迟加载,则甚至更多。

另一种方法是创建一个“路径”列,例如“1/5/19/27/34”,它将指示所有父 ID。

您还可以创建一个“last_post”表,该表将指示每个类别的最后一篇文章是什么。它也会提高你的表现。

这个帖子信息量很大:How to create a MySQL hierarchical recursive query

【讨论】:

  • 不幸的是我不知道它会有多深
【解决方案2】:

更改递归函数以接受 post 参数并比较日期。

public function lastPost($post = null)
{
    foreach ($this->threads()->orderBy('updated_at')->get() as $thread) {
        $cur_post = $thread->lastPost();
        if ($post === null) {
            $post = $cur_post;
        }
        else {
            $cur_post_date = new DateTime($cur_post->date_added); // Or whatever you use to get last post date
            $post_date = new DateTime($post->date_added);
            if ($cur_post_date > $post_date) {
                $post = $cur_post;
            }
        }  
    }
    unset($cur_post, $cur_post_date, $post_date);
    if ($this->hasSubforum()) {
        foreach ($this->subforums as $subforum) {
            $post = $subforum->lastPost($post);
        }
    }
    return $post;
}

但是,正如 Felippe Duarte 所说,递归查询数据库是一件坏事,因此如果您要在生产环境中使用该论坛,请寻找替代方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 2019-12-15
    • 2013-12-10
    • 1970-01-01
    • 1970-01-01
    • 2021-06-09
    • 1970-01-01
    相关资源
    最近更新 更多