2016-05-10 3 views
0

У меня есть система форумов с множеством категорий, которая имеет много потоков, которые имеют много сообщений.Laravel recursion - найти «последнее сообщение»

Итак, с данным форумом, я должен уметь выяснить последнее сообщение, которое имеет конкретный форум. На форуме может быть много подфорумов (они же дети). Я только смог сделать часть этого.

Таблица демонстрационный:

| 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() называется, пока форум не имеет больше подфорумов. Я получаю последнее сообщение из последней темы в подфоруме. Все идет нормально. Тем не менее, последним постом будет порядок, в котором находится подфорум. Поэтому, если последнее сообщение было во втором последнем подфоруме, оно возвращает последнее сообщение последнего подфорума, так как последний последний вопрос был возвращен последним в рекурсии.

как я могу это исправить?

Спасибо!

+0

проверить дату и установить только «$ post», если дата более поздняя (или даже «id» сообщения - при условии, что она есть, если она является серийной)? –

+0

Возможно, вы используете последний метод в коллекции $ this-> threads() ... etc, правильно? https://laravel.com/docs/5.1/collections#method-last – ExohJosh

ответ

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», который укажет на все идентификаторы родителей.

Вы также можете создать таблицу «last_post», которая укажет, что было последним сообщением для каждой категории. Это также улучшит вашу производительность.

Это сообщение имеет много информации: How to create a MySQL hierarchical recursive query

+0

К сожалению, я не знаю, насколько глубоко это будет –

0

Alter рекурсивную функцию, чтобы принять параметр пост и сравнить даты.

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 Дуарте сказал, рекурсивно запросов к базе данных, это плохо, так искать альтернативные варианты, если вы собираетесь использовать форум в производстве.

Смежные вопросы