php mysql phpbb forums read-unread

Manejo de mensajes no leídos en PHP/MySQL



phpbb forums (6)

Algo que no se sugirió fue usar Big Data para almacenar ese tipo de información, a saber, NoSQL. Efectivamente, está hecho específicamente para el manejo de este tipo de datos.

Utilizo MongoDB pero puede encontrar una aplicación NoSQL que se adapte a sus necesidades. http://nosql.findthebest.com/

Esto le permitirá escalar a otros usos aplicables en lugar de a lo que está trabajando ahora. Por ejemplo, foros, publicaciones, tickets, notas, mensajes, etc.

Otra sugerencia es que, alternativamente, puede almacenar los datos como "Metadatos", similar a la sugerencia de csv, pero dándole una estructura más flexible y almacenable, utilizando serializar para comprimir los datos para que su objeto cargue y deserialice en tiempo de ejecución. De este modo, funciona como una sesión que no caduca y que está asociada con user_id en lugar de session_id que se puede cargar a pedido y segregar como desee. Por ejemplo, cuando se carga una página de foro para un usuario en particular.

p.ej:

(Ejemplos codificados en seco: ajústelos a su propio esquema)

<?php /** array( "form_id1" => array( "post_id1", "post_id2", ), "form_id2" => array( "post_id1", "post_id2", ) ); */ $this->user->metadata = unserialize( file_get_contents( ''/metadata/forums/'' . $this->user->id ) ); if( !isset($this->user->metadata[$this->forum->id]) ){ $this->user->metadata[$this->forum-id] = array(); } if(!in_array($this->post->id, $this->user->metadata[$this->forum->id]) ){ $this->user->metadata[$this->forum-id][] = $this->post->id; } file_put_contents( ''/metadata/forums/'' . $this->user->id, serialize( $this->metadata); );

Puede intercambiar file_x_contents con su RDBMS, por ejemplo:

<?php $getMetadata = "SELECT forums FROM user_metadata WHERE user_id = $this->user->id"; $dbrs = mysqli_query( $getMetadata ); $this->user->metadata = unserialize( $dbrs[''forums''] ); $dbrs->close(); $metadata = serialize($this->user->metadata); $saveMetadata = "UPDATE user_metadata SET forums = ''$metadata'' WHERE user_id = ''$this->user->id''"; mysqli_query( $saveMetadata );

También puede hacer otras cosas como buscar mediante regexp, segregarlo más (tema, categoría, etc.), o cambiar el método para que se base en los usuarios que leen publicaciones en el foro (forum-> post-> seenby) en lugar de forum publica el usuario leído (usuario-> metadatos-> foros). Especialmente si ya tiene "Vistas totales", pero sería más difícil recuperar las publicaciones que un usuario en particular no ha leído, mientras que lo contrario es cierto con el otro método, o incluso si utiliza ambos métodos conjuntamente .

Para un proyecto personal, necesito construir un foro usando PHP y MySQL. No me es posible usar un paquete de foro ya creado (como phpBB).

Actualmente estoy trabajando con la lógica necesaria para construir una aplicación de este tipo, pero ha sido un día largo y estoy luchando con el concepto de manejar publicaciones no leídas para los usuarios. Una solución que tuve fue tener una tabla separada que esencialmente contiene todas las ID de publicación y de usuario, para determinar si se han leído:

tbl_userReadPosts: user_id, post_id, read_timestamp

Obviamente, si el ID de un usuario aparece en esta tabla, sabemos que han leído la publicación. Esto es genial, excepto si tenemos miles de publicaciones por día (que es más que posible en el sistema que se propone), y miles de usuarios. Esta tabla se volvería enorme en cuestión de días, si no de horas.

Otra opción sería rastrear la última actividad del usuario como una marca de tiempo, y luego recuperar todas las publicaciones realizadas después de que se actualizó su última actividad. Esto funciona en teoría, pero digamos que un usuario está escribiendo una publicación extremadamente larga, y mientras tanto, varios miembros también inician nuevas secuencias o responden a publicaciones en otras secuencias. Cuando el usuario envíe su nueva publicación, su última actividad se actualizará y, por lo tanto, no coincidirá con las realizadas mientras tanto.

¿Alguien tiene experiencia con esto, y cómo lo abordó?

He comprobado en phpBB y parece que el sistema asigna una sesión personalizada a cada usuario, y funciona sobre esa base, pero la documentación es bastante escasa en cuanto a cómo se trata con las publicaciones no leídas.

Pensamientos y opiniones recibidos con gratitud, como siempre.


En lugar de tener una nueva fila para cada usuario de la publicación *, puede tener un campo en la tabla de usuarios que contiene una cadena separada por comas con identificaciones posteriores que el usuario ha leído.

Obviamente, el usuario no necesita saber que hay publicaciones sin leer de hace 2 años, por lo que solo muestra "Nueva publicación" para las publicaciones realizadas en las últimas 24 horas y no está en la cadena separada por comas.

También puede resolver esto con una variable de sesión o una cookie.


Este método almacena por separado el postID acceso más reciente para cada forumID .

No es tan detallada como una solución que realiza un seguimiento de cada publicación individualmente, pero reduce la cantidad de datos que necesita almacenar por usuario y aún así proporciona una manera decente de realizar un seguimiento del historial de visitas de un usuario.

<?php session_start(); //error_reporting(E_ALL); // debug: clear session if (isset($_GET[''reset''])) { unset($_SESSION[''activity'']); } // sample data: db table with your forum ids $forums = array( // forumID forumTitle ''1'' => ''Public Chat'', ''2'' => ''Member Area'', ''3'' => ''Moderator Mayhem'' ); // sample data: db table with your forum posts $posts = array( // postID forumID postTitle ''12345'' => array( ''fID''=>''1'', ''title''=>''Hello World''), ''12346'' => array( ''fID''=>''3'', ''title''=>''I hate you all''), ''12347'' => array( ''fID''=>''1'', ''title''=>''Greetings!''), ''12348'' => array( ''fID''=>''2'', ''title''=>''Car thread''), ''12349'' => array( ''fID''=>''1'', ''title''=>''I like turtles!''), ''12350'' => array( ''fID''=>''2'', ''title''=>''Food thread''), ''12351'' => array( ''fID''=>''3'', ''title''=>''FR33 V1AGR4''), ''12352'' => array( ''fID''=>''3'', ''title''=>''CAPSLOCK IS AWESOME!!!!!!!!''), ''12353'' => array( ''fID''=>''2'', ''title''=>''Funny pictures thread''), ); // sample data: db table with the last read post from each forum $userhist = array( // forumID postID ''1'' => ''12344'', ''2'' => ''12350'', ''3'' => ''12346'' ); // reference for shorter code $s = &$_SESSION[''activity'']; // store user''s history into session if (!isset($s)) { $s = $userhist; } // mark forum as read if (isset($_GET[''mark''])) { $mid = (int)$_GET[''mark'']; if (array_key_exists($mid, $forums)) { // sets the last read post to the last entry in $posts $s[$mid] = array_search(end($posts), $posts); } // mark all forums as read elseif ($mid == 0) { foreach ($forums as $fid=>$finfo) { // sets the last read post to the last entry in $posts $s[$fid] = array_search(end($posts), $posts); } } } // mark post as read if (isset($_GET[''post''])) { $pid = (int)$_GET[''post'']; if (array_key_exists($pid, $posts)) { // update activity if $pid is newer $hist = &$s[$posts[$pid][''fID'']]; if ($pid > $hist) { $hist = $pid; } } } // link to mark all as read echo ''<p>[<a href="?mark=all">Read All</a>]</p>'' . PHP_EOL; // display forum/post info foreach ($forums as $fid=>$finfo) { echo ''<p>Forum: '' . $finfo; echo '' [<a href="?mark='' . $fid . ''">Mark as Read</a>]<br>'' . PHP_EOL; foreach ($posts as $pid=>$pinfo) { if ($pinfo[''fID''] == $fid) { echo ''- Post: <a href="?post='' . $pid . ''">'' . $pid . ''</a>''; echo '' - '' . ($s[$fid] < $pid ? ''NEW'' : ''old''); echo '' - "'' . $pinfo[''title''] . ''"<br>'' . PHP_EOL; } } echo ''</p>'' . PHP_EOL; } // debug: display session value and reset link echo ''<hr><pre>$_SESSION = ''; print_r($_SESSION); echo ''</pre>'' . PHP_EOL; echo ''<hr>[<a href="?reset">Reset Session</a>]'' . PHP_EOL; ?>

Nota: Obviamente, este ejemplo es solo para fines de demostración. Es posible que deba modificarse parte de la estructura y la lógica al tratar con una base de datos real.


Lo siento por la respuesta rápida pero solo tengo un segundo. Definitivamente no desea almacenar la información de lectura en la base de datos, como ya ha deducido, esta tabla se volvería gigantesca.

Algo intermedio entre lo que ya ha sugerido: Almacene la última actividad de los usuarios y junto con el almacenamiento de información de lo que han visto en la cookie, para determinar qué subprocesos / publicaciones ya han leído.

Esto descarga el almacenamiento a la cookie del lado del cliente, que es mucho más eficiente.


Phpbb2 ha implementado esto bastante simple. Solo muestra todas las publicaciones desde su último inicio de sesión. De esta manera, no necesita almacenar ninguna información sobre lo que el usuario realmente ha visto o leído.


Una tabla con todos los user_ids y post_ids es una mala idea, ya que crece exponencialmente. Imagínese si su solución de foro creciera a un millón de publicaciones y 50,000 usuarios. Ahora tienes 50 mil millones de discos. Eso será un problema.

El truco consiste en utilizar una tabla como usted dijo, pero solo contiene publicaciones que se han leído desde el inicio de sesión, de las publicaciones que se publicaron entre el último inicio de sesión y este último.

Todas las publicaciones realizadas antes del último inicio de sesión se consideran leídas.

IE, inicié sesión por última vez el 4/3/2011, y luego me conecto hoy. Todas las publicaciones realizadas antes del 4/3/2011 se consideran leídas (no son nuevas para mí). Todas las publicaciones entre el 4/3/2011 y ahora, no se han leído a menos que se vean en la tabla de lectura. La tabla de lectura se vacía cada vez que inicio sesión.

De esta manera, la tabla de publicaciones leídas nunca debe tener más de un par de cientos de registros para cada miembro.