Salut tout le monde !
Je cherche le meilleur moyen possible pour créer une messagerie à plusieurs participants. Dans ce post je ne vous demanderai pas de code mais juste l'architecture de la base de données (MySQL) la plus optimale pour ce problème.
Créer une messagerie avec deux participants est trivial, il suffit de créer un "post" qui appartient à un utilisateur et adressé à un utilisateur (userId pour le créateur et destId pour le destinataire par exemple).
Par contre une messagerie à plusieurs participants j'ai du mal à me visualiser comment faire ... si vous avez une idée juste pour me lancer ?
Salut @earhater,
Tu peux essayer de faire une table intermédiaire contenant l'ID du message, l'ID de l'emetteur et les IDs des destinataires (une chaine de caractères contenant les IDs séparées par des virgiles (ou autre) devrait suffire, il te suffira de faire un petit explode() et de récupérer le tout).
De cette manière tu peux faire une simple jointure afin de relier le message aux bons destinataires. Tu me suis ? :)
Salut,
Personnellement je ferais deux tables :
L'idée de @ctoulouse est pertinente aussi, en ce sens que tu peux également passer pa un groupe auquel appartiendrait un ou plusieurs utilisateur, et auquel serait jointé un message.
Après il y a plusieurs façons de faire, à toi de voir laquelle te paraît la mieux adapté à ton problème (et à ta façon de coder).
Salut les gars !
Vos réponses sont très pertinentes. Pour ce qui est de ton idée shinix elle est pas mal et j'y avait pensée mais le problème c'est que ça pose des soucis .. Par exemple comment savoir qu'il y a un nouveau messages ? Je pense reprendre l'idée de ctoulouse qui est pertinente et correspond à mes besoins. Je te remercie beaucoup pour les schémas c'est très clair !
Bonne journée à vous :)
@ earhater, tout dépend de ton code, pour savoir s'il y a un nouveau message je compare la date de connexion du membres et création du dernier message.
Après tu peux même pousser plus loin et créer une nouvelle table "topic_views" par exemple ou tu stocks l'id du membre, l'id du groupe et la date de dernière visite. (un peu la même méthode que pour un forum)
@shinix : ce n'est pas parce que l'utilisateur s'est connecté qu'il a lu les messages ;) Tandis que dans le système de ctoulouse tu peux faire un champ read contenant les id des participants dans groupe_users avec pour valeur 0 ou 1 si c'est lu. A l'affichage des messages tu passes cette valeur à 1 et la tu es sur que l'utiisateur a lu le message (vu qu'il a affiché la discution)
Après ouais c'est qu'une question de logique, "j'accroche plus" au système de ctououse que je comrpends directement (peut être grâce aux schémas :D ) je vois bien comment faire mon système avec ces 3 tables.
Re tout le monde. C'est pour vous annoncer que j'ai réussi à faire le système. Je l'ai fait en deux tables finalement avec la gestion de messages lus / non lus via un système en json (en gros les id des utilisateurs étaient associés à un boolean, quand un message est posté on repasse les booleans à false et quand l'utilisateur affiche la conversation il repasse à vrai). ça demande un peu plus de travail que le système en trois tables de ctoulouse mais ça vaut le coup de minimiser l'impact serveur :)
Je me permet de vous poster le code pour savoir ce que vous en pensez si j'ai bien fait. Je voulais utiliser deux tables pour minimiser les requêtes SQL et les jointures. Je pars donc sur deux tables :
J'ai appelé cette table mainMessages mais en gros on peut l'appeler topics (c'est juste qu'il va y avoir un forum plus tard et j'étais peu inspiré bref). Rien de bien sorcier pour cette table
Ensuite une table classique messages :
Pour ce qui est de l'ajout du message, il y a un système de requêtes en ajax pour trouver les utilisateurs. Quand un utilisateur est ajouté dans la covnersation, un champ de type hidden se met à jour avec les données id et username en format json de la conversation. à partir de là j'utilise le code suivant pour créer la conversation et ajouter le message à la conversation :
public function add()
{
$this->MainMessages = TableRegistry::get("MainMessages");
// Le code qui me permet d'obtenir en ajax les utilisateurs pour les récupérer dans la vue et es ajouter à la conversation
if($this->request->is('ajax') && isset($this->request->query['name']))
{
$name = $this->request->query['name'];
$this->autoRender = false;
$users = TableRegistry::get('Users');
$user = $users->find('all', ['limit' => 5, 'fields' => ['Users.username', 'Users.id'], 'conditions' => ['Users.username LIKE' => "%$name%"]]);
$this->response->type('json');
echo json_encode($user);
}
if($this->request->is("post"))
{
// On récupère les utilisateurs dans le champ caché au format json
$datas = $this->request->data;
$users = json_decode($datas['users']);
// On ajoute l'utilisateur courant au json
$u = new \stdClass();
$u->username = $this->Auth->user('username');
$u->id = $this->Auth->user('id');
$users[] = $u;
$this->request->data['users'] = json_encode($users);
// On parcours les utilisateurs de la conversation pour dire qu'aucun n'a lu le message de la conversation
// Sauf pour celui qui a créé la conversation
$arr = [];
foreach($users as $user)
{
if($user->id !== $this->Auth->user('id'))
{
$c = new \stdClass();
$c->id = $user->id;
$c->username = $user->username;
$c->readed = 0;
$arr[] = $c;
}
}
$messages = TableRegistry::get("Messages");
$message = $messages->newEntity([
'content' => $this->request->data['content'],
'user_id' => $this->Auth->user('id')
]);
// On sauvegarde le message
if(!$messages->save($message))
$this->Flash->error($message->errors());
// On sauvegarde a conversation
$this->request->data['read'] = json_encode($arr);
$this->request->data['user_id'] = $this->Auth->user('id');
$this->request->data['last'] = $message->id;
$mainMessage = $this->MainMessages->newEntity($this->request->data);
if($this->MainMessages->save($mainMessage))
{
$this->Flash->success("La discution a bien été ajoutée");
$this->redirect(['action' => 'index']);
}
else
$this->Flash->error($mainMessage->errors());
}
}
à ce niveau là on récupère facilement les conversations de l'utilisateur :
$id = $this->Auth->user('id');
$messages = $this->MainMessages->find('all', [
'conditions' => ["MainMessages.users LIKE" => "%:".$id."%"],
'contain' => ['Users']
]);
Bref j'ai passé un peu de temps dessus surtout que j'ai tuilsié angular pour les requetes et l'affichage des participants et que j'ai du traduire le framework (je voulais utiliser la méthode timeAgoInWords de cakephp3).
Qu'en pensez-vous ?
Et pourquoi ne pas faire simplement une table message, une table message_users, et une table message_reply
Table Message:
Id
Title
content
created
LastReply_date
LastReply_id
Table Message_reply
id
message_id
user_id
content
date
Table message_users
id
message_id
user_id
Je pense qu'il faut prendre ça comme un systeme de Forum