source open hacer foro create como bulletin board php mysql forum

open - forum phpbb



DeterminaciĆ³n de elementos no leĆ­dos en un foro (7)

Usando PHP y MySQL, tengo un sistema de foro que estoy tratando de compilar. Lo que quiero saber es cómo puedo configurarlo para que cuando un usuario lea una entrada al foro, se muestre como JUST para ese usuario, sin importar en qué foro esté, hasta que alguien más publique en él.

Actualmente, para cada hilo, tengo una tabla con un PostID, y tengo el ID de usuario que lo publicó, el ThreadID para vincularlo, el mensaje real (como texto), luego la fecha / hora en que fue publicado.

Para la lista de hilos en cada foro, está el threadID (clave principal), el ThreadName, ForumID al que pertenece, NumPosts, NumViews, LastPostDateTime y CreateDateTime. ¿Alguna ayuda?


Bobince tiene muchas buenas sugerencias. Otras pocas optimizaciones potenciales:

Escribe el nuevo "¿Es esto nuevo?" información a memcached y a una tabla de MySQL "ARCHIVE". Un trabajo por lotes puede actualizar la tabla "real".

Para cada usuario, mantenga un indicador "todo leído hasta $ date" (para cuando se hace clic en "marcar todo lo leído").

Cuando se publique algo nuevo, borre todos los indicadores de "se ha leído", que mantiene baja la cantidad de "indicadores" y la tabla solo puede estar (topic_id, user_id) - sin marcas de tiempo.


La solución tradicional es una tabla de unión algo similar a:

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) );

con lastread actualizado cada vez que se lee un tema. Al mostrar la lista de temas, si los topics.lastupdated son> topicviews.lastread, hay publicaciones nuevas.

¡La solución tradicional es basura y matará a su base de datos! No lo hagas!

El primer problema es que una escritura en cada vista de tema pondrá al servidor de la base de datos de rodillas en un foro ocupado, especialmente en las tablas MyISAM que solo tienen bloqueos a nivel de tabla. (No use tablas MyISAM, use InnoDB para todo menos para búsqueda de texto completo).

Puede mejorar esta situación un poco si solo se molesta en escribir a través del último tiempo de lectura cuando realmente se están leyendo mensajes nuevos en el tema. Si topic.lastupdated <topicviews.lastread no tiene nada que ganar actualizando el valor. Aun así, en un foro muy utilizado esto puede ser una carga.

El segundo problema es una explosión combinatoria. Una fila por usuario por tema pronto se suma: ¡solo mil usuarios y mil temas y tiene potencialmente un millón de filas de vistas temáticas para almacenar!

Puede mejorar esta situación un poco al limitar el número de temas recordados para cada usuario. Por ejemplo, podría eliminar cualquier tema de la tabla de vistas cuando sea anterior a cierta edad, y simplemente asumir que todos los temas antiguos son ''leídos''. Esto generalmente necesita una tarea de limpieza en segundo plano.

Otros enfoques menos intensivos incluyen:

  • solo almacenando un último tiempo de lectura por foro
  • solo se almacena una última visita por usuario en todo el sitio, lo que mostraría como ''nuevo'' solo las cosas actualizadas desde la visita previa del usuario (sesión)
  • no almacena ninguna información lastread en absoluto, sino que incluye la hora de la última actualización en la propia URL de un tema. Si el navegador del usuario ha visto el tema recientemente, recordará la URL y la marcará como visitada. A continuación, puede usar CSS para marcar los enlaces visitados como ''temas que no contienen mensajes nuevos''.

Las ideas generales aquí son correctas, pero han pasado por alto algunas soluciones obvias al problema de la escalabilidad.

@bobince: El segundo problema es una explosión combinatoria. Una fila por usuario por tema pronto se suma: ¡solo mil usuarios y mil temas y tiene potencialmente un millón de filas de vistas temáticas para almacenar!

No necesita almacenar un registro en la tabla "topicviews" si alguien no ha visto ese hilo. Simplemente mostraría un tema como si tuviera publicaciones no leídas si se devuelve nulo O de la última hora de lectura es <hora_última_post. Esto reducirá ese "millón" de filas quizás por un orden de magnitud.

@gortok: hay muchas formas de hacerlo, pero cada uno crece exponencialmente a medida que el usuario visita el sitio.

En este caso, archiva un foro después de n-posts o n-weeks y, cuando lo bloquea, limpia la tabla "topicviews".

Mi primera sugerencia es obvia y no tiene inconvenientes. Mi segundo reduce la usabilidad en los temas archivados, pero ese es un pequeño precio a pagar por un foro rápido. Los foros lentos son dolorosos de leer y publicar.

¿Pero honestamente? Probablemente no necesite preocuparse por la escalabilidad. Incluso un millón de filas realmente no son tantas.


No hay una manera fácil de hacer esto. Hay muchas maneras de hacerlo, pero cada uno crece exponencialmente a medida que el usuario visita el sitio. Lo mejor que puede hacer y aún mantener el rendimiento es tener una marca de tiempo y marcar todos los foros que se hayan actualizado desde la última visita como "no leídos".


Se puede almacenar en otra tabla UserID, threadID, LastReadDateTime cuando el usuario lee esa cadena.

if (LastPostDateTime > LastReadDateTime) you got an unread post.

Lamentablemente tienes una gran sobrecarga, en cada lectura tendrás una escritura.


Simplemente puede usar la funcionalidad del navegador del usuario y anexar el último mensaje en el enlace al hilo de esta manera: "thread.php? Id = 12 & lastpost = 122"

Al hacer uso de: visitó en su CSS, puede mostrar las publicaciones que el usuario ya leyó diferentes de las que no leyó.


Se utiliza el navegador del usuario de la funcionalidad y agrega la última ID de la publicación en el enlace del hilo. Después del uso de: visitado en CSS, puede mostrar todo el hilo que no haya leído el usuario.