Administrateur PHPfrance |
3131 Messages
14 juin 2006, 19:34
Il va alors falloir multiplier le nombre de lignes par le nombre d'utilisateurs, ou alors un post lu par quelqu'un apparait lu pour tout le monde.
Je ne sais pas quel système utiliser phpBB, mais personnellement je gèrerais ça avec une tierce table :
posts_lus (
user_id, post_id).
Définir qu'un post est lu :
REPLACE INTO posts_lus (user_id,post_id) VALUES ($user_id, $post_id) (REPLACE est identique à INSERT, au détail près que si la ligne à insérer existe déjà pour une clé primaire ou unique, la ligne est supprimée avant insertion, ce qui évite de faire une requête de vérification en plus pour rien).
Définir qu'un post est non lu :
DELETE FROM posts_lus WHERE user_id=$user_id AND post_id=$post_id
Savoir si un post est lu :
SELECT 1 FROM posts_lus WHERE used_id=$user_id AND post_id=$post_id doit renvoyer une ligne.
Savoir qui a lu un post :
SELECT user_id FROM posts_lus WHERE post_id=$post_id
Récupérer la liste des posts lus :
SELECT post_id FROM posts_lus WHERE user_id=$user_id
Les inconvénients de cette approche :
- la table va grossir très rapidement, dès que quelqu'un lit un post, la table gagne une ligne. Ainsi elle ne fera que grossir, et ne maigrira a priori jamais (sauf suppression de post ou d'utilisateur).
- la fonction "marquer tous les posts comme lus" pour l'utilisateur est fortement consommatrice de ressources.
- la fonction "voir tous les sujets non lus" est également fortement consommatrice.
Une autre approche serait peut-être plus intelligente : une table
posts_non_lus (
user_id, post_id).
Définir qu'un post est non lu :
REPLACE INTO posts_non_lus (user_id,post_id) VALUES ($user_id, $post_id).
Définir qu'un post est lu :
DELETE FROM posts_non_lus WHERE user_id=$user_id AND post_id=$post_id.
Savoir si un post est lu :
SELECT 1 FROM posts_lus WHERE used_id=$user_id AND post_id=$post_id ne doit rien renvoyer.
Marquer tous les sujets comme lus :
DELETE FROM posts_non_lus WHERE user_id=$user_id.
Cette approche résout les problèmes de l'approche précédente (la taille variera continuellement, mais tendra idéalement vers 0), mais impose d'ajouter une opération couteuse au moment de l'envoi de chaque nouveau sujet :
Code : Tout sélectionner
$query = "INSERT INTO posts_non_lus (user_id, post_id) VALUES ";
$q_users = mysql_unbuffered_query("SELECT id FROM users");
while ($row = mysql_fetch_row($q_users)) {
$query .= " ({$row[0]}, $post_id),";
}
mysql_query(substr($query,0,-1));
Deux requêtes dont une assez lourde, dont on peut diminuer l'impact grâce à unbufferd_query.
Les fonctions "savoir qui a lu tel post" et "quels posts a lu tel users" sont équivalentes à leurs homologues de l'approche précédente. Mais on peut considérer qu'elles sont moins souvent nécessaires que "savoir quels posts n'ont pas été lus par tel user".
Voilà une petite analyse de ce que je ferais, j'opterais probalement pour la seconde approche. À voir maintenant : comment font les forums "célebres" qui implémentent cette fonction.