The traditional solution is a join table something like rows:
CREATE TABLE topicviews ( userid INTEGER NOT NULL, topicid INTEGER NOT NULL, lastread TIMESTAMP NOT NULL, PRIMARY KEY (userid, topicid), FOREIGN KEY (userid) REFERENCES users(id), FOREIGN KEY (topicid) REFERENCES topics(id) );
with lastread is updated every time you read the topic. When a topic list is displayed, if topic.lastupdated is> topicviews.lastread, new messages appear.
The traditional solution is garbage and kill your database! Do not do this!
The first problem is that writing to each topic view will soon bring the database server to its knees in a busy forum, especially on MyISAM tables that only have table-level locks. (Do not use MyISAM tables, use InnoDB for everything except full-text search).
You can improve this situation a little only by bothering to write after the last reading, when there are new posts in this thread. If topic.lastupdated <topicviews.lastread you have nothing to get by updating the value. However, in a heavily used forum, this can be a burden.
The second problem is a combinatorial explosion. One line for each user in the topic will be added soon: a total of a thousand users and a thousand topics, and you have potentially a million lines to view!
You can improve the situation a bit by limiting the number of topics remembered for each user. For example, you can remove any topic from the presentation table when it is older than a certain age, and just assume that all old topics are “read”. Usually this is a cleaning task that should be performed in the background.
Other, less intense approaches include:
- saving only one last time on the forum
- only saving one last time for each user throughout the site, which will be displayed as “new” only updating, since the user's previous visit (session)
- Do not store all the latest information, but including the most recent updates in the URL itself. If the user's browser has recently viewed a topic, they will remember the URL and mark it as having visited. You can then use CSS to search for visited links as "topics without new posts."