Aide pour la gestion des messages des utilisateurs

Eléphant du PHP | 417 Messages

17 mars 2013, 15:34

Bonjour,

je suis en train de créer un système de messagerie qui permet l'envoie des messages entre les utilisateur de mon site (c'est pas les messages instante).

Je sais pas comment vous vous précédez pour un tel système, mais moi j'ai créé deux tables, messages et discussion

Niveau BDD :

messages : idMessage, from, to, sujet, text, etat(lu, en attend), date (clé première : idMessage)
discussion : idDiscussion, idMessage (clé première : idDiscussion, clé étranger : idMessage)

un message appartient a une seul discussion
une discussion peut contenir 1,N messages

Niveau web :

pour un nouveau message j'ai un formulaire avec un input, textaria et un bouton pour envoyer le formulaire
quand un nouveau message est envoyé, j'insert les informations de message dans la table messages je récupère son id et je crée une nouvelle discussion (vu que c'est un nouveau message) donc j'insert l'id de message que j'ai récupérer et le idDiscussion il est générer tous seul (auto incrémentation)

jusque ici y a pas de soucis
mon problème c'est lors d'une réponse (c'est a dire associer un message a une discussion qui existe déjà)

ce que je compte faire c'est lors d'une réponse j'aurai un formulaire avec un textaria, un bouton pour envoyer la réponse et un input hidden qui contient le id de la discussion
et quand on valide le formulaire j’insère les infos de message comme avant je récupère son id et c'est là que j'ai le problème pour insérer dans la table discussion

sachant que j'ai un id de discussion donc j'ai pas besoin que ça soit auto incrémenté :s

d'ou viens mon problème ? manque un champ dans ma table discussion ? j'avoue que j'arrive pas a réfléchir pour trouver une solution :s c'est pour ça que je reviens vers vous

Merci d'avance

Eléphant du PHP | 120 Messages

17 mars 2013, 15:45

Quel est le rapport avec l'orientation objet ?

Pourquoi tes champs from et to sont dans messages et non pas dans discussion ? Il faudrait aussi penser à uniformiser la nomenclature de tes noms de tables et champs. Une fois le singulier, une fois le pluriel, une fois en français, une fois en anglais.
Pour ce qui est de ton problème. Tu t'es emmêlé les pinceaux. Il faut te poser la question de savoir "Qu'est-ce qu'un message ? Qu'est-ce qu'une discussion ?"

Un message appartient à une discussion, une discussion peut avoir plusieurs messages. Ton architecture ne le permet pas - elle permet d'associer un message à une discussion - pas plus. Il faut donc relier messages à discussion et non pas l'inverse.

Eléphant du PHP | 417 Messages

17 mars 2013, 16:04

Merci pour votre réponse Perine

pour répondre a ton message
Quel est le rapport avec l'orientation objet ?
j'ai pas fait attention quand je l'ai publié comme j'ai l'habitude de publier dans ce forum de POO

Pourquoi tes champs from et to sont dans messages et non pas dans discussion ?
parce que je pense que c'est plus pratique que dans discussion, un message concerne deux utilisateurs et c'est la même chose pour une discussion donc c'est plus pratique dans la table message pour éviter des requête complexe dans certains cas
Il faudrait aussi penser à uniformiser la nomenclature de tes noms de tables et champs. Une fois le singulier, une fois le pluriel, une fois en français, une fois en anglais.
je t'assure que au niveau de ma BDD sont bien uniformisé c'est juste j'ai écris les nom vite
Pour ce qui est de ton problème. Tu t'es emmêlé les pinceaux. Il faut te poser la question de savoir "Qu'est-ce qu'un message ? Qu'est-ce qu'une discussion ?"
y a pas vraiment une grand différence entre les deux, un message concerne deux utilisateur et la discussion aussi, la seul différence c'est que un message fait partie d'une discussion (arrêt moi si je me trompe)
Un message appartient à une discussion, une discussion peut avoir plusieurs messages. Ton architecture ne le permet pas - elle permet d'associer un message à une discussion - pas plus. Il faut donc relier messages à discussion et non pas l'inverse.
cette partie je l'ai pas trop compris ?
messages -------1,1--------discussions
discussions-----1,N---------messages

donc la clé étranger sera l'id de message dans la table discussion non ?

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

17 mars 2013, 16:35

Quel est le rapport avec l'orientation objet ?
j'ai pas fait attention quand je l'ai publié comme j'ai l'habitude de publier dans ce forum de POO
Modération :
Afin d'obtenir plus de réponses, le sujet a été déplacé dans un forum plus approprié.

Merci de prendre le temps de lire les règlements
ainsi que l'intitulé de chaque forum avant de poster un nouveau sujet.
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer

Eléphant du PHP | 120 Messages

17 mars 2013, 16:37

From et To n'ont rien perdu dans des messages, il s'agit de données relatives aux discussions. Dans la table message, un champ user-id est suffisant pour identifier qui a écrit ce message.

Regarde ta structure actuelle :

Code : Tout sélectionner

MariaDB [test]> create table messages ( -> message_id int auto_increment primary key, -> date datetime not null, -> from int not null, -> to int not null); Query OK, 0 rows affected (0.06 sec) MariaDB [test]> create table discussions ( -> discussion_id int auto_increment primary key, -> message_id int not null, -> constraint foreign key (message_id) references messages(message_id)); Query OK, 0 rows affected (0.08 sec)
La règle pour des bases de données relationnelles est : une ligne par entité. Dans ton cas, il faut avoir plusieurs lignes de discussions par discussion.
C'est donc mauvais.
Il est beaucoup plus simple et propre de faire comme ça :

Code : Tout sélectionner

MariaDB [test]> create table discussions ( -> discussion_id int auto_increment primary key, -> user1 int not null, -> user2 int not null, -> subject varchar(64) not null); Query OK, 0 rows affected (0.10 sec) MariaDB [test]> create table messages ( -> message_id int auto_increment primary key, -> user_id int not null, -> date datetime not null, -> discussion_id int not null, -> constraint foreign key (discussion_id) references discussions (discussion_id)); Query OK, 0 rows affected (0.06 sec)

Code : Tout sélectionner

MariaDB [test]> insert into discussions values (null, 1, 2, 'Discussion A'); Query OK, 1 row affected (0.03 sec) MariaDB [test]> insert into messages values (null, 1, now(), 1); Query OK, 1 row affected (0.04 sec) MariaDB [test]> insert into messages values (null, 2, now(), 1); Query OK, 1 row affected (0.04 sec) MariaDB [test]> insert into messages values (null, 1, now(), 1); Query OK, 1 row affected (0.03 sec) MariaDB [test]> insert into discussions values (null, 2, 1, 'Discussion B'); Query OK, 1 row affected (0.04 sec) MariaDB [test]> insert into messages values (null, 2, now(), 2); Query OK, 1 row affected (0.03 sec) MariaDB [test]> insert into messages values (null, 2, now(), 1); Query OK, 1 row affected (0.02 sec) MariaDB [test]> insert into messages values (null, 1, now(), 2); Query OK, 1 row affected (0.07 sec)

Code : Tout sélectionner

MariaDB [test]> select * from discussions; +---------------+-------+-------+--------------+ | discussion_id | user1 | user2 | subject | +---------------+-------+-------+--------------+ | 1 | 1 | 2 | Discussion A | | 2 | 2 | 1 | Discussion B | +---------------+-------+-------+--------------+ 2 rows in set (0.00 sec) MariaDB [test]> select * from messages; +------------+---------+---------------------+---------------+ | message_id | user_id | date | discussion_id | +------------+---------+---------------------+---------------+ | 1 | 1 | 2013-03-17 15:31:40 | 1 | | 2 | 2 | 2013-03-17 15:31:47 | 1 | | 3 | 1 | 2013-03-17 15:31:51 | 1 | | 4 | 2 | 2013-03-17 15:32:22 | 2 | | 5 | 2 | 2013-03-17 15:32:26 | 1 | | 6 | 1 | 2013-03-17 15:32:30 | 2 | +------------+---------+---------------------+---------------+
Maintenant, nous voulons sélectionner tous les messages de la discussion A :

Code : Tout sélectionner

MariaDB [test]> select messages.message_id, messages.user_id, messages.date -> from discussions -> inner join -> messages -> on -> messages.discussion_id = discussions.discussion_id -> where discussions.discussion_id = 1; +------------+---------+---------------------+ | message_id | user_id | date | +------------+---------+---------------------+ | 1 | 1 | 2013-03-17 15:31:40 | | 2 | 2 | 2013-03-17 15:31:47 | | 3 | 1 | 2013-03-17 15:31:51 | | 5 | 2 | 2013-03-17 15:32:26 | +------------+---------+---------------------+ 4 rows in set (0.00 sec)

Eléphant du PHP | 417 Messages

17 mars 2013, 16:48

merci pour ton effort perine,

le problème c'est que j'ai déjà des requete compliqué et si je déplace le from et to dans ma table discussion ça me fera le bordel et plein de requete a modifier :s

je peux pas faire simple et créer juste la table discussion avec un seul champ (idDiscussion) que je met comme clé étranger dans la table message ?

Eléphant du PHP | 120 Messages

17 mars 2013, 16:50

Je ne sais pas et je ne vais pas t'aider à mal structurer ta base de données. Tu verras la merde que ce sera dans deux mois si tu gardes ça comme ça - surtout si tu veux ajouter des fonctionnalités à ta messagerie (genre des discussions de > 2 personnes).

Et remplacer des requêtes inutilement compliquées par des requêtes aussi simple que celle que je t'ai montrée ne devrait pas être trop problématique. Surtout que ta messagerie n'est pas encore terminée ; raison de plus pour le faire correctement :)

Eléphant du PHP | 417 Messages

17 mars 2013, 16:59

oui c'est vrai que il vaut mieux les modifier dés début ...

par exemple j'ai une requete pour afficher a l'utilisateur connecté ses message reçu, envoyer

donc comme information j'ai que l'id de l'utilisateur en question avec ta méthode (les from et to dans la table discussion) tu fera comment pour afficher les message reçu de l'utilisateur connecté ? sachant que si dans la BDD y a plusieurs message qui appartiens a une discussion il faut l'afficher juste une fois dans la liste des messages reçu ?

Eléphant du PHP | 120 Messages

17 mars 2013, 17:41

Ayant réparti les messages en discussions, c'est une mauvaise idée de n'afficher que les messages qu'on a envoyé ou qui ont été envoyé à soi-même. Il faut afficher une liste de discussions à laquelle a participé l'utilisateur. Pour cela une simple requête avec "where user1 = USER_ID or user2 = USER_ID"

Si tu veux le faire quand même, ce n'est pas u problème non plus, car tu peux te servir du user_id dans messages pour afficher les messages que tu as envoyé ou faire une jointure sur discussions pour afficher les messages que tu n'as pas envoyé (et donc par conséquent qu'on t'a envoyé).

Eléphant du PHP | 417 Messages

17 mars 2013, 18:01

ah donc ça sert a rien la page "message envoyer" maintenant
j'aurai juste une page qui m'affiche toutes les discussion dans l'utilisateur a participé c'est bien ça ?

Eléphant du PHP | 120 Messages

17 mars 2013, 18:12

Et bien c'est l'idée derrière le fait de ne pas avoir que des messages, mais aussi des discussions. L'idée de messages uniquement commence quand même à dater (mails, etc.). Une application qui centralise tout peut permettre la notion de discussions :)

Eléphant du PHP | 417 Messages

17 mars 2013, 18:21

Et bien c'est l'idée derrière le fait de ne pas avoir que des messages, mais aussi des discussions. L'idée de messages uniquement commence quand même à dater (mails, etc.). Une application qui centralise tout peut permettre la notion de discussions :)
ok j'avais pas pensé à sa en même temps j'avais juste un système de messagerie interne et j'avais pas le système de la discussion maintenant que je voulais la mettre a jour j'avais pas pensé que la page message envoyé n'est plus obligatoire :)

j'aurai besoin de votre aide pour la requete qui me permet d'afficher les 10 dernières discussions qui concerne l'utilisateur,

avant de penser a organisé mes messages sous form d'une discussion

j'avais des requetes de ce type : pour afficher la liste des messages reçu :
SELECT messengers . * , u1.nameUser AS nameUser1, u1.surnameUser AS surNameUser1, u2.nameUser AS nameUser2, u2.surnameUser AS surNameUser2
		FROM users AS u1, users AS u2, messengers
		WHERE u1.idUser = messengers.to
		AND u2.idUser = messengers.from
		AND messengers.to = 1
		ODERE BY dateMessenger DESC
		LIMIT 0,10;
pour afficher les 10 dernière message reçu

donc si j'utilise ta solution ma requête pour afficher les 10 dernières discussions:
SELECT DISTINCT(messengers.idDiscussion),  messengers.*, u1.nameUser AS nameUserTo, u1.surnameUser AS surNameUserTo, u2.nameUser AS nameUserFrom, u2.surnameUser AS surNameUserFrom
FROM users AS u1, users AS u2, messengers, discussions
WHERE u1.idUser = discussions.to
AND u2.idUser = discussions.from
ODERE BY dateMessenger DESC
LIMIT 0,10;
c'est bien comme ça ?

Eléphant du PHP | 120 Messages

17 mars 2013, 19:05

select
    discussions.subject,
    max(messages.date) last_date
from
    discussions
inner join
    messages
on
    messages.discussion_id = discussions.discussion_id
group by
    messages.discussion_id
order by
    max(messages.date) desc
limit 10

Eléphant du PHP | 417 Messages

17 mars 2013, 19:09

oui mais j'ai besoin aussi des informations sur les deux utilisateur, sur le message ..

Eléphant du PHP | 120 Messages

17 mars 2013, 19:20

Dans ce cas, je ne puis que te recommander de lire de la documentation sur les bases de données parce que je ne vais pas t'écrire toutes les requêtes SQL dont tu vas avoir besoin. Il s'agit là encore de simple jointures. Il n'y a que les informations sur le dernier message (mis à part sa date) qui sera un peu plus dur à récupérer en une seule requête SQL parce que MySQL ne respecte pas le standard SQL2002.