Для удаления/переноса потребуется пересчет для всех юзеров. Можно поднимать флаг (дату), чтобы каждый юзер после удаления постов в разделе однократно пересчитывал себе t_unread_count тогда активные модерские правки не будут так тормозить. Но us2f растет в ширину )))
А если на каждого юзера заводить отдельный файл в формате Json в виде массива: [{"регистрация":"дата","топы":{"id":"время просмотра",...}}] Для того, чтобы определить является ли тема новой сначала сравниваем дату последнего сообщения с датой регистрации, если больше, то с датой последнего посещения темы. При просмотре темы, обновляем значение массива["топы"][id топика] на now(). Нагрузка на сервак будет куда меньше, а утечки данных не будет, т.к. перезапись файла будет только с 1 сессии. + если массив будет численным (не ассоциативным) JSON_en(de)code будут работать быстро.
Alehandr представь, 1000 юзеров (это даже очень мало, в принципе), 10К тем (почти много, да ладно) и 100к постов, если каждый будет этот файл обрабатывать (а это серилизованный массив, значит он грузится весь в память) при каждом просмотре (ты ведь не знаешь, смотрел эту тему юзер, пока не откроешь файл)... ну как бы долго и памятижрущще получается
antonn Ну да, про память не подумал... Но я бы всеравно реализовал на файлах, только надо придумать как получше будет...
Файлы, файлы... Всёравно в базе хранить надо. Самый приемлимый вариант это следить за выбранными пользователем темами в режиме live в базу и остальное по схеме PHPBB с куками и последним временем входа. Для кеширования выборок с базы юзаю memcached или xcache
куки - это привязка к машине, а так я на работе и дома вижу привычное положение дел - где я был и где небыл
antonn Честно я не сильно смотрел как в PHPBB там сделано толком. Вобщем то записывается время последнего посещения и показывает новое после этого момента. А конкретно 100% правильное слежение можно сделать только за активными темами.
100% работающее я описывал уже, а "правильно" понятие растяжимое а "вход" клиента из той же серии, что и "юзеры онлайн". я браузер могу раз в час обновлять, по дефолту на куче сайтов сессия будет пересоздаваться, на втором часе у меня исчезнут маркеры?
не реализовывал такого. но вообще в голову первое пришло - пишем юзеру в два поля ид максимальной темы, и ид макимальной мессаги(если форум написан с одной таблицей для мессаг и тем - то еще лучше). Потом смотрим - если в теме присутствует комменты с ид выше нашего - значит новое =) но тут идет другое. глядим последнюю тему - и все предыдущие кагбе прочитано. "на середине поста появилось странное ощущение, что что-то неверно. так и вышло"
всю тему не читал поэтому могу повторить предложенный ранее вариант.. и всё же 1. в начало каждого скрипта добавляем код, который записывает в куку или в БД время (время последнего посещения) 2. проверяем есть ли сессия в которой записано время последнего посещения. если нет создаём сессию, и все темы где есть посты добавленные позднее времени последнего посещения помечаем как непрочитанные если тема пользователю интересна он её прочтёт, если нет то при следующем посещении она не будет и мазолить ему глаза своей подсветкой
Фигня в том, что нет такого понятия как "последнее посещение". Браузер запрашивает страничку, получает в ответ, никаких "вы сечаст на сайте" и "последний раз вы заходили". Я могу случайно обновить страницу браузера и через час увижу, что "новых" тем совсем мало осталось Так же лично я считаю, что у юзера нету куков
пришел в голову похожий функционал, глядя на форумы, включая этот. внести тему в черный список. в двух вариантах - не как новые темы/форумы и скрыть вообще
здесь этот функционал плохо сделан. На pyha.ru/forum стоит SMF, там реально круто непрочитанные отмечаются. Может кто-то поставит-поковыряет его?
Сделал форум. Форумы и темы помечаются на ура. Задачка плёвая, как 2 пальца. Не буду полностью расписывать решение, нудная хрень, всё равно потом выложу в открытый доступ. Правда не спрашивайте когда, делал под заказ, нужно время, чтобы открыть код. Могу таблички шпиона показать и куски кода: [sql]CREATE TABLE IF NOT EXISTS `forums_spy` ( `user_id` int(11) default NULL, `forum_id` int(11) default NULL, `time` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=UTF8;[/sql] [sql]CREATE TABLE IF NOT EXISTS `forum_topics_spy` ( `user_id` int(11) default NULL, `forum_id` int(11) default NULL, `topic_id` int(11) default NULL, `time` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=UTF8;[/sql] При выводе форумов: Выбираем статистику шпиона по форумам: PHP: <?php if($USER_ID != 1) // для гостя не мониторим { $result = $DB->query("SELECT `forum_id`, `time` FROM `{prefix}forums_spy` WHERE `user_id` = ".$USER_ID); while($row = $DB->fetch_assoc($result)) { $forums_spy[$row['forum_id']] = $row['time']; } } Дальше при обходе форумов делаем такую фишку: PHP: <?php if(isset($forums_spy[$forum['id']])) // У шпиона есть запись на текущий форум { if($forums_spy[$forum['id']] >= $forum['last_post_time']) // Форум прочитан { $forum_read = ($category['open'] and $forum['open'])? /*форум прочитан | открыт*/ : /*форум прочитан | закрыт*/ ; } else { $forum_read = ($category['open'] and $forum['open'])? /*форум не прочитан | открыт*/ : /*форум не прочитан | закрыт*/ ; } } else // Запись отсутствует { if($forum['topics_num'] and $USER_ID != 1) // Форум не прочитан { $forum_read = ($category['open'] and $forum['open'])? /*форум не прочитан | открыт*/ : /*форум не прочитан | закрыт*/ ; $forum_spy_insert[] = '('.$USER_ID.', '.$forum['id'].', 0)'; // Собираем данные для шпиона } else { $forum_read = ($category['open'] and $forum['open'])? /*форум прочитан | открыт*/ : /*форум прочитан | закрыт*/ ; ; } } После обхода форумов надо сделать записи шпиону на те форумы про которые он не знает: PHP: <?php if(isset($forum_spy_insert)) $DB->query("INSERT INTO `{prefix}forums_spy` VALUES ".implode(', ', $forum_spy_insert)); При выводе топиков: Вычищаем статистику по устаревшим топикам: PHP: <?php $DB->query("DELETE FROM `{prefix}forum_topics_spy` WHERE `forum_id` = ".get('id')." AND `time` <= ".(time() - $forums[$forum_category_id][get('id')]['topics_outdated_time'])); Выбираем статистику: PHP: <?php if($USER_ID != 1) { $result = $DB->query("SELECT `topic_id`, `time` FROM `{prefix}forum_topics_spy` WHERE `user_id` = ".$USER_ID." AND `forum_id` = ".get('id')); while($row = $DB->fetch_assoc($result)) { $forum_topics_spy[$row['topic_id']] = $row['time']; } } При обходе топиков проверяем так: PHP: <?php if(isset($forum_topics_spy[$row['id']])) // У шпиона есть запись на текущую тему { $forum_topic_read = ($forum_topics_spy[$row['id']] >= $row['last_post_time'])? true : false ; } else // Запись отсутствует { $forum_topic_read = ($USER_ID != 1 and $row['last_post_time'] > time() - $forums[$forum_category_id][get('id')]['topics_outdated_time'])? false : true ; } При выводе постов начинается самое веселье: PHP: <?php if($USER_ID != 1) { // Провереям наличие записи у шпиона на текущую тему $result = $DB->query("SELECT `time` FROM `{prefix}forum_topics_spy` WHERE `user_id` = ".$USER_ID." AND `topic_id` = ".$forum_topic['id']); $forum_topic_spy = $DB->fetch_row($result); if(!$DB->num_rows($result) or $forum_topic_spy[0] < $forum_topic['last_post_time']) // Тема не прочитана { // Правим статистику шпиона if(!$DB->num_rows($result)) { $DB->query("INSERT INTO `{prefix}forum_topics_spy` VALUES (".$USER_ID.", ".$forum_topic['forum_id'].", ".$forum_topic['id'].", ".$forum_topic['last_post_time'].")"); } else { $DB->query("UPDATE `{prefix}forum_topics_spy` SET `time` = ".$forum_topic['last_post_time']." WHERE `user_id` = ".$USER_ID." AND `topic_id` = ".$forum_topic['id']); } // Кол-во не устаревших прочитанных тем в форуме $result_spy_read = $DB->fetch_row($DB->query("SELECT COUNT(*) FROM `{prefix}forum_topics_spy`, `{prefix}forum_topics` WHERE `user_id` = ".$USER_ID." AND `{prefix}forum_topics_spy`.`forum_id` = `{prefix}forum_topics`.`forum_id` AND `{prefix}forum_topics`.`forum_id` = ".$forum_topic['forum_id']." AND `topic_id` = `id` AND `time` >= `last_post_time` AND `time` > ".(($forum_spy_time = time()) - $forums[$forum_category_id][$forum_topic['forum_id']]['topics_outdated_time']))); // Кол-во устаревших тем в форуме $result_spy_outdated = $DB->fetch_row($DB->query("SELECT COUNT(*) FROM `{prefix}forum_topics` WHERE `forum_id` = ".$forum_topic['forum_id']." AND `last_post_time` <= ".($forum_spy_time - $forums[$forum_category_id][$forum_topic['forum_id']]['topics_outdated_time']))); // Кол-во прочитанных тем + кол-во устаревших тем = кол-ву тем в форуме -> форум прочитан if($result_spy_read[0] + $result_spy_outdated[0] == $forums[$forum_category_id][$forum_topic['forum_id']]['topics_num']) { $DB->query("UPDATE `{prefix}forums_spy` SET `time` = ".$forums[$forum_category_id][$forum_topic['forum_id']]['last_post_time']." WHERE `user_id` = ".$USER_ID." AND `forum_id` = ".$forum_topic['forum_id']); } } } Вот такая ацкая хрень. Алгоритм, насколько я понимаю, очень похож на алгоритм из IPB. Такой вывод делаю на основе изучения базы. Вот такие пироги.
сделал свой вариант. Помечает темы с непрочит. мессагами. Всего нужна 1 таблица с ид юзера и текстовым полем для пар ид_топика+mktime. Еще чуток допилю, чтоб самоочищалось поле и чтоб можно было просмотреть новые сообщения отдельно. А так ничё вроде.