[RESOLU] Regrouper les messages privés avec GROUP BY

Eléphant du PHP | 386 Messages

25 juin 2013, 02:57

Bonjour,

J'ai une messagerie privé avec système de messages lus / non lus.
J'affiche la liste des messages lus et non lus dans un toggle.

Voici la table `wa_messagerie` :

- id
- id_expediteur
- id_destinataire
- message
- timestamp

Le problème se trouve à l'affichage (Voir l'image ci-dessous) :

Image

Les messages sont évidemment créés par moi pour tester :mrgreen:
Le message grisé est un message non lu
Les messages en fond blanc sont des messages lus


J'aimerais que les doublons de messages (de Guillaume pour l'exemple avec l'image) d'un même membre soient regroupés, même ceux qui sont déjà lus.


Voici mes 2 requêtes utilisées avec GROUP BY qui est un échec :cry: :

Une qui affiche les messages non lus (lu=0)
Une qui affiche les messages lus (lu=1)
<?php
$req = $connect->prepare('SELECT wa_communaute.id, message, id_destinataire, id_expediteur, lu, prenom, nom, timestamp FROM wa_messagerie RIGHT JOIN wa_communaute ON id_expediteur = wa_communaute.id WHERE lu=0 AND id_destinataire = :id_expediteur GROUP BY id_expediteur, wa_communaute.id ORDER BY timestamp DESC');
$req->execute(array(':id_expediteur'=>$_SESSION['id']));
while ($data = $req->fetch()) {
	echo '<li>';
	echo '<a href="" class="msg_nonlu">';
	echo '<img src="../img/upload/'.$data['id'].'-mini.png" class="floatl" alt="" style="margin-right: 5px;" />';
	echo '<div style="line-height: 17px;">';
	echo '<div class="author" style="font-weight: bold; color: #333;">'.$data['prenom'].' '.$data['nom'].'</div><div class="message" style="color: #666;">'.$data['message'].'</div><div class="time" style="color: #aaa">'.getRelativeTime($data['timestamp']).'</div>';
	echo '</div>';
	echo '</a>';
	echo '</li>';
}
$req->closeCursor();
								
$req = $connect->prepare('SELECT wa_communaute.id, message, id_destinataire, id_expediteur, lu, prenom, nom, timestamp FROM wa_messagerie RIGHT JOIN wa_communaute ON id_expediteur = wa_communaute.id WHERE lu=1 AND id_destinataire = :id_expediteur GROUP BY id_expediteur, wa_communaute.id ORDER BY timestamp DESC');
$req->execute(array(':id_expediteur'=>$_SESSION['id']));
while ($data = $req->fetch()) {
	echo '<li>';
	echo '<a href="" class="msg_lu">';
	echo '<img src="../img/upload/'.$data['id'].'-mini.png" class="floatl" alt="" style="margin-right: 5px;" />';
	echo '<div style="line-height: 17px;">';
	echo '<div class="author" style="font-weight: bold; color: #333;">'.$data['prenom'].' '.$data['nom'].'</div><div class="message" style="color: #666;">'.$data['message'].'</div><div class="time" style="color: #aaa">'.getRelativeTime($data['timestamp']).'</div>';
	echo '</div>';
	echo '</a>';
	echo '</li>';
}
$req->closeCursor();
?> 
Merci d'avance pour votre aide :wink:

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

25 juin 2013, 16:07

Salut,


Il n'y a pas de doublon dans l'image, juste trois message distinct.


Va falloir être plus clair si tu veux que l'on t'aide.
Pour info group by ne sert qu'avec des fonctions de groupe (sum, count, avg etc).
Donc la ça ne sera pas la solution ;)


@+
Il en faut peu pour être heureux ......

Eléphant du PHP | 386 Messages

25 juin 2013, 16:30

Alors moi j'aimerais que les messages d'un même membre soient regroupés en une seule conversation.
Et je ne sais pas comment procéder :cry:

ViPHP
ViPHP | 2577 Messages

25 juin 2013, 16:31

Tu peux créer une vue :
SELECT max(id) as id_message, id_destinataire, id_expediteur, count(*) as nb
FROM wa_messagerie 
GROUP BY id_expediteur, id_destinataire
(voir CREATE VIEW)

Et ensuite tu adaptes tes select avec une jointure sur cette vue pour récupéré le texte du message (le dernier), les noms ...

Eléphant du PHP | 386 Messages

25 juin 2013, 16:53

A moins que je créé une table `conversations` qui relie les 2 membres et le dernier message reçu :

id AI
id_expediteur
id_destinataire
last_message
timestamp

Avec un id unique pour chaque conversation.
Comme ça je regroupe les messages en conversation ? :wink:

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

25 juin 2013, 20:18

non tu ajoute une auto jointure sur la table existante, le champs doit être nullable et n'est alimenté que lorsque l'on répond à un message précédent.
alter table wa_messagerie add iddiscution int null;
alter table wa_messagerie add constraint fk_discution foreign key (iddiscution)  references wa_messagerie(id)
du coup lorsque tu crée le premier message cette nouvelle colonne est nulle.
Lorsque tu crée la réponse tu met dans cette colonne l'id du message de départ.

pour récupérer une discution tu tri sur l'iddiscution et tri par date.


Pour info timestamp est un mot clef SQL est donc tu ne devrais pas l'utiliser comme nom de colonne,

sinon a tu simplement test ton select avec un order by id_expediteur, lechampdedateheuredumessage ?

@+
Il en faut peu pour être heureux ......

Eléphant du PHP | 386 Messages

25 juin 2013, 21:02

Alors j'ai fais ça :
SELECT wa_communaute.id, message, id_destinataire, id_expediteur, lu, prenom, nom, timestamp FROM wa_messagerie RIGHT JOIN wa_communaute ON id_expediteur = wa_communaute.id ALTER TABLE wa_messagerie ADD id int NULL; WHERE lu=0 AND id_destinataire = :id_expediteur GROUP BY id_expediteur, wa_communaute.id ORDER BY timestamp DESC;
                                                  
SELECT wa_communaute.id, message, id_destinataire, id_expediteur, lu, prenom, nom, timestamp FROM wa_messagerie RIGHT JOIN wa_communaute ON id_expediteur = wa_communaute.id ALTER TABLE wa_messagerie ADD constraint id_expediteur FOREIGN KEY (id)  REFERENCES wa_messagerie(id) WHERE lu=1 AND id_destinataire = :id_expediteur GROUP BY id_expediteur, wa_communaute.id ORDER BY timestamp DESC;
Voici ma table wa_messagerie :

id
id_expediteur
id_destinataire
message
lu
timestamp (Je changerais le nom de la colonne une fois le pb reglé)

Et plus rien ne s'affiche, je crois que c'est pas comme ça que ça marche parce que normalement la première requête récupère les messages non lus et la deuxième les messages lus :cry:

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

25 juin 2013, 21:56

bon alors non

le alter table c'est du DDL (data definition language) ça n'a rien a faire dans du DML (Data Manipulation Language).

comme déja dit le group ne sert à rien.

tuto sur SQL : http://sqlpro.developpez.com


@+
Il en faut peu pour être heureux ......

Eléphant du PHP | 386 Messages

25 juin 2013, 21:59

Tu ne pourrais pas me montrer comment utiliser ALTER TABLE dans mon cas ?
J'ai vraiment du mal à comprendre avec les tutos :(

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

25 juin 2013, 22:18

tu a le code c'est a utiliser une fois il s'agit ici d'ajouter la colonne et la contrainte de clef étrangère

http://sqlpro.developpez.com/cours/sqla ... rtie2#L7.6
Il en faut peu pour être heureux ......

Eléphant du PHP | 386 Messages

26 juin 2013, 00:39

Donc il faudrait le placer où ce code :
ALTER TABLE wa_messagerie ADD iddiscution int NULL;
ALTER TABLE wa_messagerie ADD constraint fk_discution FOREIGN KEY (iddiscution)  REFERENCES wa_messagerie(id)
<li class="dropItem dropdown"><a href="#" class="menuHeaderJewelMessage dropdown-toggle <?php if($count>0): ?>notif_msg<?php endif; ?>"<?php if($count>0): ?> data-notif_msg="<?php echo $count;?>" <?php endif; ?> data-toggle="dropdown"></a>
						<ul class="dropdown-menu" style="width: 300px; min-height: 330px;">
							<li class="dropArrowMenu"></li>
							<li style="display: block;height: 20px;border-bottom: 1px solid #dadada;"><a href="#" style="float: left; font-size: 11px; font-weight: bold; margin: -2px 0 0 10px; color: #003d57;">Boite de réception (<?php echo $count;?>)</a><a href="#" style="margin: -2px 10px 0 0; float: right; font-size: 11px; color: #003d57;">Envoyer un message</a></li>
							<?php
								$req = $connect->prepare('SELECT wa_communaute.id, message, id_destinataire, id_expediteur, lu, prenom, nom, timestamp FROM wa_messagerie RIGHT JOIN wa_communaute ON id_expediteur = wa_communaute.id WHERE lu=0 AND id_destinataire = :id_expediteur ORDER BY id_expediteur, timestamp DESC');
								$req->execute(array(':id_expediteur'=>$_SESSION['id']));
								while ($data = $req->fetch()) {
								echo '<li>';
								echo '<a href="" class="msg_nonlu">';
								echo '<img src="../img/upload/'.$data['id'].'-mini.png" class="floatl" alt="" style="margin-right: 5px;border-radius: 5px;" />';
								echo '<div style="line-height: 17px;">';
								echo '<div class="author" style="font-weight: bold; color: #333;">'.$data['prenom'].' '.$data['nom'].'</div><div class="message" style="color: #666;">'.$data['message'].'</div><div class="time" style="color: #aaa">'.getRelativeTime($data['timestamp']).'</div>';
								echo '</div>';
								echo '</a>';
								echo '</li>';
								}
								$req->closeCursor();
								
								$req = $connect->prepare('SELECT wa_communaute.id, message, id_destinataire, id_expediteur, lu, prenom, nom, timestamp FROM wa_messagerie RIGHT JOIN wa_communaute ON id_expediteur = wa_communaute.id WHERE lu=1 AND id_destinataire = :id_expediteur ORDER BY id_expediteur, timestamp DESC');
								$req->execute(array(':id_expediteur'=>$_SESSION['id']));
								while ($data = $req->fetch()) {
								echo '<li>';
								echo '<a href="" class="msg_lu">';
								echo '<img src="../img/upload/'.$data['id'].'-mini.png" class="floatl" alt="" style="margin-right: 5px;border-radius: 5px;" />';
								echo '<div style="line-height: 17px;">';
								echo '<div class="author" style="font-weight: bold; color: #333;">'.$data['prenom'].' '.$data['nom'].'</div><div class="message" style="color: #666;">'.$data['message'].'</div><div class="time" style="color: #aaa">'.getRelativeTime($data['timestamp']).'</div>';
								echo '</div>';
								echo '</a>';
								echo '</li>';
								}
								$req->closeCursor();
							?> 
						</ul>
					</li>