- Поисковые системы
- Практика оптимизации
- Трафик для сайтов
- Монетизация сайтов
- Сайтостроение
- Социальный Маркетинг
- Общение профессионалов
- Биржа и продажа
- Финансовые объявления
- Работа на постоянной основе
- Сайты - покупка, продажа
- Соцсети: страницы, группы, приложения
- Сайты без доменов
- Трафик, тизерная и баннерная реклама
- Продажа, оценка, регистрация доменов
- Ссылки - обмен, покупка, продажа
- Программы и скрипты
- Размещение статей
- Инфопродукты
- Прочие цифровые товары
- Работа и услуги для вебмастера
- Оптимизация, продвижение и аудит
- Ведение рекламных кампаний
- Услуги в области SMM
- Программирование
- Администрирование серверов и сайтов
- Прокси, ВПН, анонимайзеры, IP
- Платное обучение, вебинары
- Регистрация в каталогах
- Копирайтинг, переводы
- Дизайн
- Usability: консультации и аудит
- Изготовление сайтов
- Наполнение сайтов
- Прочие услуги
- Не про работу
Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий
var_dump($comments); какой у вас, если конечно не огромный:D
var_dump($comments); какой у вас, если конечно не огромный:D
вот кусок кидаю:
---------- Добавлено 04.11.2013 в 19:54 ----------
Сделал так, выводит только последний добавленный по списку parent_id:
Название темы прочитайте и самый верхний комментарий сами.
Это и ребёнок может с 2-мя уровнями :)
Точно - я ошибся, ТС сорри. Хорошо что на форуме есть такие люди как Leonindkg - всегда с готовностью укажут на чужие ошибки.
for($i=0;$i<count($comments);$i++){if(!empty($comments[$i]["parent_id"])){
$pcm[$comments[$i]["parent_id"]]=$comments[$i];
}
}
Вот тут комменты дочерние затирать будут друг друга, то есть одному родителю - один дитя
Вот тут комменты дочерние затирать будут друг друга, то есть одному родителю - один дитя
точно! и еще пару ошибок исправил:
И как же обойти эту проблему?
Рекурсия при "бесконечной" вложенности - это зло.
Сортировка массива в памяти при большом количестве комментов - это зло.
Не секрет, что страницу комментов чаще читают, чем постят комменты. Поэтому выдачу надо делать максимально быстро с минимальной нагрузкой на сервер. А вот когда поступает новый пост, тут и надо делать всю работу.
У меня на компе уже больше 10 лет хранится такая вот статья. Не помню уже даже откуда слил.
Статья подробная и длинная. Поэтому постить буду в несколько этапов.
---------- Добавлено 04.11.2013 в 23:50 ----------
Алгоритм построения древовидного форума без использования рекурсии
Копия от 21 декабря 2002 года. Оригинал статьи
Постановка задачи
При выводе древовидного форума возникает проблема быстродействия, так как обработка деревьев требует рекурсивных алгоритмов, что в случае форума на основе базы данных означает как минимум один SQL запрос на каждое выводимое сообщение. При большом размере треда вследствие большого количества запросов быстродействие страницы падает катастрофически. Рассмотрим способ, позволяющий избежать этого и вывести древовидный форум при помощи всего одного запроса SQL (плюс один дополнительный запрос для нужд разбиения на страницы).
Если рассмотреть задачу подробно, оказывается, что проблему представляет только сортировка писем внутри треда. Применим стандартный прием для таких ситуаций: предварительную сортировку, осуществляемую еще на этапе вставки письма в тред. Для этого в таблице писем создадим дополнительное поле X типа INT для этой цели. При этом проблема быстродействия перемещается в момент вставки письма, но тут мы ее легко решаем при помощи алгоритма со сборкой мусора, где мусором является неравномерность распределения значений поля X по допустимому диапазону (от 0 до MAXINT).
Реализация
Итак, если Вы еще не заснули от теоретического описания ситуации, перейдем к практической реализации. Запросы SQL я буду давать в диалекте MySQL, а алгоритмическую часть — в синтаксисе PHP, потому что на данный момент пара PHP/MySQL является наиболее распространенным и приемлемым вариантом для построения подобных вещей.
Опишем таблицу для хранения сообщений. В данном случае я дам только поля, необходимые для функционирования алгоритма, и абстрактное поле Data, в котором хранятся данные, относящиеся к письму. В реальных условиях это поле заменяется на поля TEXT Body, VARCHAR(255) Subject, VARCHAR(255) FromUser и так далее — все, что Вам надо для конкретной реализации.
Описание полей
ID
Идентификатор письма
ForumID
Идентификатор форума
ThreadID
Идентификатор треда
ParentID
Идентификатор исходного письма для данного ответа. Ноль, если письмо начинает новый тред.
X
Последовательность вывода писем в треде
Level
Отступ при выводе письма
Data
Данные письма
Алгоритмы
Итак, что нам нужно уметь делать с этим хозяйством: а) вставлять письмо, начинающее новую тему; б) вставлять ответ на уже существующее письмо; в) выводить все это красивыми ступеньками, причем на каждом уровне письма отсортированы по времени в обратном порядке, то есть самый последний ответ сверху, ближе всего к оригиналькому письму (на которое отвечали), остальные уезжают вниз. Рассмотрим каждое из этих действий.
Вставка нового письма
Исходные данные: $ForumID, $data. Мы должны сформировать номер для нового треда и вставить письмо. Делается это двумя запросами:
Поля X и Level мы не устанавливаем, и они принимают значение по умолчанию, то есть ParentID=0 (это не ответ), X=0 (первое письмо в треде) и Level=0 (нулевой уровень, нет отступа). Обратите внимание на два момента. Во-первых, я использовал для хранения номера нового треда переменную MySQL, потому что снаружи MySQL это число мне просто не нужно. Этого делать не обязательно, Вы можете передавать это число из одного запроса в другой через переменную языка программирования. Второй момент связан с тем, что номер ThreadID является глобальным для всех форумов в данной базе. Тут есть некоторое искушение добавить в первый запрос WHERE ForumID=$ForumID и тем самым «сэкономить» идентификаторы тредов, но не надо ему поддаваться. Потому что есть такая дополнительная операция, как перенесение треда в другой форум, и нам лучше будет не искать новый ThreadID при этом.
Добавление ответа на письмо
Самая интересная ситуация, потому что именно тут мы осуществляем всю грязную работу. Сначала опишем, каким образом формируются поля, а потом общий алгоритм. Исходные данные: переменная $parent, в которой лежит запись исходного письма (мы ее туда взяли по mysql_fetch_object()), а также переменная $data, где находятся полученные от пользователя данные.
ForumID
Такой же, как у $parent (ForumID=$parent->ForumID). Если только Вы не предусмотрите возможности отвечать из одного форума в другой.
ThreadID
Такой же, как у $parent (ThreadID=$parent->ThreadID).
ParentID
Идентификатор $parent (ParentID=$parent->ID).
Level
На единицу больше, чем у $parent (Level=$parent->Level).
X
Тут-то кабан и порылся. Мы должны вставить новое письмо между $parent и следующим письмом треда, либо после $parent, если $parent — последнее письмо треда. Для этого берем диапазон, снизу ограниченный $parent->X, а сверху — либо X следующего письма треда, либо максимальным возможным значением MAXINT. И ставим X прямо в центр этого диапазона, вычисляя его по нехитрой формуле X=(MinX+MaxX)/2. При этом может возникнуть ситуация, когда вследствие накопления мусора у нас уже не осталось зазора между $parent и следующим письмом треда. Это может случиться, к примеру, если будет много ответов на одно письмо (с каждым новым ответом диапазон уменьшается в два раза). Выявив эту ситуацию, мы должны запустить единственный длительный процесс в этом алгоритме: сборку мусора. Она будет выражаться в том, что мы заново перенумеруем весь тред по полю X, выровняв все интервалы между сообщениями. Предварительно можно проверить, а влезет ли в этот тред что-либо еще вообще. Простейший способ это сделать — посчитать количество писем в треде и сравнить его с MAXINT/2. Конечно, при этом мы получим тред в два раза менее емкий, чем теоретический предел, но не будем заморачиваться на этом. Лично я надеюсь в этой жизни не увидеть ТАКИХ дискуссий. После сборки мусора у нас гарантированно есть интервал между $parent и следующим письмом, так что после этого мы смело идем на процедуру вставки ответа в момент вычисления диапазона для X.
Теперь все вместе
Примерно так. Естественно, этот фрагмент кода можно рассматривать только как чисто условный, так как с целью упрощения тут делаются вещи, которые обычно делаться не должны: «обработка» ошибки при помощи die(), использование низкоуровневых функций php для обращения к mysql безо всякого враппера, и так далее.
Вывод форума
Итак, теперь у нас есть сортировка внутри тредов, так что мы можем смело вывести весь форум одним запросом. Исходные данные — $ForumID.
Правда, реальность несколько отличается от данной теории. Проблема в том, что форум надо выводить не весь, а постранично, и хорошо бы бить на страницы по границам тредов. Для этого нам придется сделать дополнительный запрос, чтобы выбрать все треды, нужные для данной страницы. Исходные данные: $ForumID, $PageSize — количество тредов на страницу, $CurrentPage — текущая страница.
В данном случае сортировка осуществляется по номеру треда, но можно также сортировать по «свежести» сообщений, если хранение этой информации предусмотрено (ORDER BY MAX(CreatedAt_field)), или еще как-нибудь.
Как видите, данный принцип позволяет свести наиболее частую операцию — показ дерева форума — к минимальному алгоритму всего с парой запросов. Форумы на этом принципе, реализованные на ASP, а затем PHP, эксплуатируются автором несколько лет и показали высокую эффективность данного подхода.
Комментарии — на akul@otamedia.com
Copyright © 2002 by Alexey Kulentsov
---------- Добавлено 05.11.2013 в 00:18 ----------
Нашел источник: http://db-maker.narod.ru/forum.htm
Kuasar, спасибо) хорошая статья