Merci pour l'érudit :lol: :hahaha:
Je suis justement en train de refléchir à un système de messagerie privée avec multiples destinataires sur mon site, les principaux problèmes auxquels j'ai pensé sont :
Ces contraintes posées, le modèle s'impose de lui-même :
message ( id, id_expediteur, login_expediteur, sujet, corps )
message_destinataire ( id_message, id_destinataire, login_destinataire )
boite ( id_personnage, id_message, etat, dossier )
etat est un ENUM('read', 'unread')
dossier est une chaine, ou si on ne veut pas gérer la création de dossier un ENUM('inbox', 'sent', 'trash', 'archives')
Les actions principales se traduisent comme ça :
naholyr(#1) envoie un message à elazard(#2) et Maegia(#3)
Maegia(#3) lit le message
Maegia(#3) supprime le message (sans passer par la corbeille)
On est tranquille ça n'a rien changé au contenu de la table `message_destinataire`, donc il apparait toujours comme faisant partie des destinataires
elazard(#2) se désinscrit du site
Idem, ça n'a rien changé
Pour afficher un message, on peut faire une jointure entre `message` et `message_destinataire` :Ça ne fait qu'une requête, par contre chaque ligne répète le sujet et le message, dans notre exemple ça donnerait ce résultat :Donc quand on va parcourir les résultats de notre requête on va simplement définir sujet et corps au premier passage, et les destinataires dans les passages suivants.
Je suis justement en train de refléchir à un système de messagerie privée avec multiples destinataires sur mon site, les principaux problèmes auxquels j'ai pensé sont :
- Si un destinataire supprime le message de sa boite, il ne faut surtout pas que ça supprime le message de toutes les boites de tout le monde :lol: cela n'impose pas grand-chose comme contrainte en fait, si ce n'est que si on ne veut pas avoir un système de suppression lourdingue, il vaut mieux stocker message d'un côté et destinataires de l'autre avec une clé étrangère.
- Si un destinataire supprime le message de sa boite, il ne faudrait pas qu'il disparaisse de la liste des destinataires pour les autres utilisateur qui ont accès au message. cela implique qu'il faut stocker quelque part la liste initiale des destinataires qui elle ne sera jamais modifiée.
- Si un destinataire disparait (désinscription) il faudrait quand-même que son login reste dans la liste des destinataires d'un message. Cela implique que la liste initiale des destinataires doit contenir l'id ET le login du destinataire.
Ces contraintes posées, le modèle s'impose de lui-même :
message ( id, id_expediteur, login_expediteur, sujet, corps )
message_destinataire ( id_message, id_destinataire, login_destinataire )
boite ( id_personnage, id_message, etat, dossier )
etat est un ENUM('read', 'unread')
dossier est une chaine, ou si on ne veut pas gérer la création de dossier un ENUM('inbox', 'sent', 'trash', 'archives')
Les actions principales se traduisent comme ça :
naholyr(#1) envoie un message à elazard(#2) et Maegia(#3)
Code :
INSERT INTO message (id_expediteur, login_expediteur, sujet, corps) VALUES (1, 'naholyr', 'coucou', 'mon message');
INSERT INTO message_destinataire (id_message, id_destinataire, login_destinataire) VALUES ($id_message, 2, 'elazard'), ($id_message, 3, 'Maegia');
INSERT INTO boite (id_personnage, id_message, etat, dossier) VALUES (1, $id_message, 'unread', 'sent'), (2, $id_message, 'unread', 'inbox'), (3, $id_message, 'unread', 'inbox');
Maegia(#3) lit le message
Code :
UPDATE boite SET etat='read' WHERE id_personnage=3 AND id_message=$id_message;
Maegia(#3) supprime le message (sans passer par la corbeille)
Code :
DELETE FROM boite WHERE id_personnage=3 AND id_message=$id_message
elazard(#2) se désinscrit du site
Code :
DELETE FROM boite WHERE id_personnage=2
Pour afficher un message, on peut faire une jointure entre `message` et `message_destinataire` :
Code :
SELECT id_expediteur, login_expediteur, sujet, corps, id_destinataire, login_destinataire FROM message, message_destinataire WHERE id_message=$id_message
Code :
+---------------+------------------+--------+-------------+-----------------+--------------------+
| id_expediteur | login_expediteur | sujet | corps | id_destinataire | login_destinataire |
+---------------+------------------+--------+-------------+-----------------+--------------------+
| 1 | naholyr | coucou | mon message | 2 | elazard |
| 1 | naholyr | coucou | mon message | 3 | Maegia |
+---------------+------------------+--------+-------------+-----------------+--------------------+
Code PHP :
<?php
$result = $db->query("SELECT id_expediteur, login_expediteur, sujet, corps, " .
"id_destinataire, login_destinataire FROM message, message_destinataire " .
"WHERE id_message=?", $id_message);
if (!$result) {
// Erreur dans la requête, message d'erreur
$erreur = "Erreur SQL";
} else {
$first_loop = true;
// On parcourt les résultat
while ($row = $db->fetch($result)) {
if ($first_loop) { // Premier résultat rencontré : on stocke les infos communes
$message = array(
'sujet' => $row['sujet'],
'corps' => $row['corps'],
'expediteur' => array( $row['id_expediteur'] , $row['login_expediteur'] ),
'destinataires' => array()
);
$first_loop = false;
}
// Ajout d'un destinataire
$message['destinataires'][] = array( $row['id_destinataire'] , $row['login_destinataire'] );
}
if ($first_loop) { // Si $first_loop est toujours vrai, cela signifie qu'il n'y avait aucun résultat
// Message d'erreur
$erreur = "Aucun message correspondant à l'id $id_message";
} else {
// On peut afficher le message
// Le message a ses infos directement dans le tableau
// L'expéditeur et chaque destinataire est un couple, exemple : list($id, $login) = $message['expediteur']
}
}
Si on veut afficher différemment les personnages qui n'existent et les personnages qui existent, je pense qu'on peut difficilement se passer d'une deuxième requête (mais je ne suis pas un chef en SQL donc c'est peut-être possible). Quelque chose comme SELECT id FROM personnages WHERE id IN (1,2,3) (pour notre exemple). Et on récupère la liste des id des personnages qui existent, ainsi on peut faire que les logins des persos qui n'existent plus ne soient pas cliquables (là on est dans le deuxième «else» du code précédent) :
Code PHP :
<?php
$ids = array($message['expediteur'][0]);
foreach ($message['destinataires'] as $destinataire) {
$ids[] = $destinataire[0];
}
$result = $db->query("SELECT id FROM personnage WHERE id IN (" . implode(',',$ids) . ")");
if (!$result) {
// Erreur dans la requête, message d'erreur
$erreur = "Erreur SQL";
} else {
// On crée un tableau qui dit si l'utilisateur existe ou non
$perso_existe = array();
while ($row = $db->fetch($result)) {
$perso_existe[$row['id']] = true;
}
// On poursuit…
}