Помогите разобраться, как реализуется система подсветки (ну жирным, чтоли) тем в форумах, в которых появились новые сообщения? Причем не по последнему посещению, когда вышел-вошел, и все "прочитано", а так, чтобы оно запоминало, и пока не откроешь урл темы - не пометится как "прочитаное". Можно ли такое выполнить на стороне сервера, очень не хочу юзать куки. Как вообще такое реализуется?
Куками это и не сделаешь, если тем штук 200, фигу они у тя поместяться в куках. К тому же куку можно удалить. Я сделал такую систему используя базу данных. Честно говоря сильно нагружает базу - таблица с прочитано/непрочитано занимает много места, да и есть места, где её использование весьма тормозит и обойти эту проблему мне пока не удалось. Думаю, пробую, тестирую...
У меня тоже есть неполноценное решение, работает у меня на форуме. Например у меня 20 форумов. Создаём массив, и по id форума (в виде индекса массива) пишем в него максимальный рейтинг позиционирования последнего прочитанного топика и время создания последнего поста. С каждым новым сообщением максимальный рейтинг позиционирования топика растёт, а время создания последнего поста обновляется. Сериализуем массив и кладём его в куку. При каждом проходе программы сверяем максимальный рейтинг позиционирования форума с тем, что у нас есть в куке, так же сверяем время. Например рейтинг в форуме № 3 больше на 10 того, что лежит в куках, а время больше только в 7 верхних темах. Значит в форуме № 3 появилось 7 непрочитанных тем. Чтобы пометить форум как непрочитанный сверяем время последнего поста в форуме с временем из куков. Алгоритм быстрый, но слегка некорректный. Если зайти в форум и начать чтение тем не с конца, то непрочитанные темы до прочитанной только что пометятся как прочитанные. Хотя, можно привыкнуть.
так в том то и проблема, я иногда думаю, что лучше уж никакого решения, чем то, которое может повести себя неожиданно...
Моё ведёт себя вполне предсказуемо, просто алгоритм не позволяет абсолютно наверняка точно помечать непрочитанные темы. Если читать новые темы с конца, то всё будет нормально и темы будут помечаться правильно, а стоит перескочить через одну непрочитанную тему с конца, как та темы через которую перескочили пометится как прочитанная. Это и есть косяк моего алгоритма. Откровенно говоря я сам голову ломаю над правильным алгоритмом. Было у меня решение с базой, но блин, + ещё запросы, нафиг нафиг. Надо идти по другому пути. p.s. добавлю, то, что работает у меня сейчас - это временное решение.
Я использую два метода. Первый - частичное отслеживание. Заключается в сравнении даты появления в теме последнего сообщения и даты последнего визите пользователя, плюс проверка находится ли идентификатор темы в массиве идентификаторов прочитанных тем, хранимом в сессии пользователя. Таким образом осуществляется точное отслеживание прочитанности тем в пределах одной сессии пользователя. Второй - прецизионное отслеживание. Если у пользователя есть право на прецизионное отслеживание, движёк использует метод занесения идентификаторов пользователей и тем в специальную таблицу, при появлении нового сообщения в теме все записи с идентификатором этой темы из этой таблицы удаляются. Для экономии места и ресурсов отслеживание производится на глубину 6 месяцев (или столько, сколько установит администратор), все более старые темы автоматически признаются прочитанными, добавление в них новых сообщений запрещается, а записи из таблицы отслеживания удаляются.
Помоему самая удачная идея это следующее: Таблица прочитенного/непрочитанного имеет два типа записей: Принудительное слежение (типа юзер тыкает галочку "Следить за темой") и обычное слежение (оно по дефолту). При принудительном слежении за темой система следит всегда. При обычном слежение происходит только когда тема обновляеться и пока юзер её переодически просматривает. Как только тема не обновляеться (условно) неделю, все записи для слежения за ней (кроме принудительного слежения) удаляються и в теме ставим в дополнительное поле ID последнего запощенного сообщения. Как только тема обновляеться, она подсвечиваеться, но всем юзерам тыкаеться как в последнее непрочитанное сообщение в следующее после той ID, которую мы записали в специальное поле (при условии, что пользователь принудительно не следит за темой. Если слежение принудительное, мы знаем куда конкретно его надо тыкнуть). Что-то типа этого.
сэр, есть, сэр! суть алгоритма такова: храним в таблице n-n связи между пользователями и просмотренными ими темами. записи старше определённого возраста - удаляем и считаем темы старше этого возраста просмотренными.
dark-demon Человек читал тему. Тема заглохла на месяц. Записи удалились, соответственно неизвестно до какого места человек дочитал тему. Через месяц кто-то отпостил в тему пару новых сообщений. Человек читавший тему зашел и увидел что она обновилась. Внимание ВОПРОС: При подсветке что в теме есть новые сообщения на какое сообщение мы будем кидать пользователя при клике на "Показать непрочитанные сообщения"?
armadillo Это на самом деле есть нехорошо. Человек, который тему видит в первый раз - да, ему так и надо. А если там 20 страниц и я их уже читал, я хочу видить 21-ю сразу. Но как сделать так, что бы я мог бы увидеть 21-ю страницу спустя месяц, но при этом не нагружая базу данных (потому что храние M:N создаёт такое кол-во данных, что база не очень быстро работает), хотя с этим я справился использую memcache и выбирая зарание всю инфу. Вся сложность в том, что когда отображаешь список форумов, что-бы узнать прочитан он весь или нет приходиться делать большой вложенный запрос, который для каждого форума в моём случае в среднем варианте перебирает от 200 до 2 тысячь записей (т.к. я модер, то я просматриваю ВСЕ темы, посему записей у меня ОЧЕНЬ много и серверу честно говоря не очень весело с этой хернёй возиться). Я могу выложить свою версию того, как я сделал вывод форумов, топиков и сообщений (могу в вариации с memcache) и базу. Не ленитесь и вы, давайте на примерах и тестировании придём к конкретному какому-то варианту хорошего алгоритма для общего случая (типичный форум аля PHPBB), который: 1). Не создаёт кучи записей 2). Не грузит сильно базу (особенно при большом кол-ве народа) 3). Позволяет нормально пользователям его читать, даже если тема не обновлялась долго (но пользователь её активно читал), что-бы не возникало такого, что я читал 20 страниц, напостил кучу сообщений, а форум предлагает мне читать всё заного через 2 месяца простоя.
должны быть границы возможного хранения записей. иначе просто объем инфы будет слишком велик. Есть еще кнопка "пометить все прочтенным". обновление целого раздела имхо стоит обновлять при добавлении каждого поста. update viewedforums set viewed=0 where forums_id=$fid and viewed=1 минимальный по объему вариант просто чтения - бинарное поле в ветке с битом на каждого юзера. Все равно слишком объемно. Долго хранить надо только сознательно поставленные в наблюдение темы.
на то, которое имеет дату не старше критической. не вижу проблемы. вообще, по хорошему, нужно хранить инфу о прочитанных сообщениях, но это крайне избыточно. поэтому мы просто храним для каждой темы дату её прочтения и все сообщения старше этой даты считаем прочитанными. если дата прочтения не указана - считаем её равной "дате среза".
Да, но каждый читал её в разное время, а кто-то вообще не читал. Вот и получаеться, что для тех кто читал - надо хранить данные. А те кто не читал, читают её с первой страницы соответственно. Но прочитав её, у них опять же появляються записи о том, что они читали. И дело даже не столько в том, надо или не надо это хранить, а в том, как построить базу так, что бы это не тормозило, потому что проверить, а есть ли непрочитанные темы в целом форуме весьма ресурсоёмкая задача для SQL сервера. Это кстати единственное место где у меня случился затык, который я никак не могу обойти. При выводе списка тем и сообщений проблем давно нету - там SQL сервер я даже не мучаю - memcache рулит. Но вот вывод списка форумов - это смерть.. PHP: <?php mysql_query('SELECT far_id, far_title, for_id, for_title, for_descr, for_topics, for_messages, frm_id, frm_creation_date, frt_id, (SELECT count(*) FROM forums_topics LEFT JOIN forums_last_readed ON frt_id = flr_frt_id AND flr_prf_id = '.$user_id.' WHERE frt_for_id = for_id AND frt_last_frm_id > IFNULL(flr_frm_id, 0)) AS last_readed_msg, FROM forums LEFT JOIN forums_messages ON for_last_frm_id = frm_id LEFT JOIN forums_topics ON frm_frt_id = frt_id LEFT JOIN profiles ON frm_prf_id = prf_id', $database); ?> Subselect отвечает за проверку наличия непрочитанных тем в форуме. Если last_readed_msg > 0, значит они есть. Как переделать/соптимизировать я просто уже не знаю...
почему это? если в теме хотябы 10 страниц - никто её с начала читать не будет. не просёк, а зачем при выводе списка форумов информация о прочитанных темах?
dark-demon Что-бы пометить, в каком форуме есть новые сообщения, а в каком нету. Ну в принципе читать то не будет, но это мелочь, потому что тыкнуть правильно мне надо уже читавшего тему юзера, а не того, кто тему вообще ещё не читал.
не вижу разницы, дату или пост_ид если нет данных, то тема прочитана полностью. если добавляется новый пост, то [sql]insert into юзеры*темы select ".$topic_id.", ".$post_id.", user_id from users left join юзеры*темы ut on ut.topic_id=".$topic_id." and ut.user_id=users.user_id where ut.user_id is null[/sql] . при прочтении - убивать из юзеры*темы.
Psih, думается мне, что выборка одной записи куда быстрее чем выборка всех и подсчёт их количества... я тоже ещё можно номер поста в теме записывать, смотря что выгоднее... ты предлагаешь записывать инфу о непрочитанных темах? ну это глупо. мало кто читает все темы, а на крупном форуме - при всём желании не успеешь в итоге у тебя таблица будет офигенных размеров...
[sql]update viewedforums set viewed=0 where forums_id=".$fid." and viewed=1 and user_id=".$user_id[/sql] или [sql]delete from viewedforums where forums_id=".$fid." and user_id=".$user_id[/sql] Это уж чего больше будет - мертвых душ или активных участников. Имхо мертвых душ будет больше, то есть добавлять надо просмотренные и убивать имеющие новые сообщения.
впрочем, эта информация, думается мне, бесполезна она предполагает, что пользователь будет тыкать в форум, если в нём есть новые сообщения (кстати, тоже вариант - записывать не только соответствия юзеров темам, но и юзеров форумам). но это не удобно! на этом форуме я просто тыкаю "отобразить темы с последнего посещения" и из полученного списка отбираю интересное. есть другой сайт с более чем 50 форумами. 90% из них мне абсолютно не интересны. поэтому мне приходится тыкать по интересным мне форумам (4-8 шт) - задалбывает. кнопка "отобразить темы с последнего посещения" выдаёт 90% мусора. было бы удобней, если бы можно было отметить галками интересные мне форумы и искать новые сообщения только в них. и опять же список форумов остаётся не у дел...
фильтр "не показывать этот форум ваще" почему, просто он составляется только по актуальным форумам. "Добавить форум/тему в дайджест"