Aller au menu - Aller au contenu

[Plan du site] Vous êtes ici --- > Le Site du Zéro > Les tutoriels > Non-Officiels > Site Web > PHP > Systèmes complets > Messagerie privée à plusieurs participants > Le système > L'accueil de la Messagerie Privée > Lecture du tutoriel

L'accueil de la Messagerie Privée

Vous vous apprêtez à lire un tutoriel rédigé par un membre de ce site. Malgré tout le soin que ce membre a pu apporter au tutoriel, nous ne pouvons pas garantir que les informations contenues sur cette page sont exactes à 100%. Merci de garder cela en tête lorsque vous lirez cette page ;o)
Avatar
Auteur : NL
Note : 10 / 20 (4 votes)
Visualisations : 2 724


Plus d'informations Plus d'informations
Cette page affichera la liste des MP du membre dans un tableau contenant le titre, la liste des participants et la dernière réponse de chaque MP. Il y aura aussi une petite image pour indiquer si vous avez lu (ou non) le MP.

Comme je l'ai indiqué au début, je pars du principe que vous avez créé un système de membres, et l'id du membre qui va sur la page est $id_membre.
Sommaire du chapitre :
Icône du chapitre
Chapitre précédent Sommaire Chapitre suivant

Préparation de la page

Avant de voir la requête qui nous permettra d'afficher tous nos MP avec toutes les informations que l'on veut, il faut préparer la page, notamment la pagination.
Effectivement, il est impensable de ne pas mettre en place une pagination si vous autorisez 100 MP.

Compter le nombre de MP



On commence d'abord par compter le nombre de MP, afin de pouvoir en déduire le nombre de pages.
Pour ça, on va compter le nombre d'entrées dans la table mp_participantsmembre_id vaut l'id du membre, et où mpp_supprimer vaut 0, car on affiche seulement les MP que le membre désire voir. (Je rappelle que si mpp_supprimer vaut 0, c'est que le membre n'a pas supprimé le MP, mais s'il vaut 1, c'est qu'il l'a fait.)

Code : PHP
1
2
3
4
5
6
7
8
9
<?php
 
$sql = 'SELECT COUNT(*)
        FROM mp_participants
        WHERE membre_id = '.$id_membre.' AND mp_supprimer = 0';
$requete = mysql_query($sql) or die(mysql_error());
$nb_mp = mysql_result($requete, 0);
 
?>


mysql_result permet de récupérer un champ - ce qui est notre cas ici - et cette fonction est plus rapide que les autres. Je vous renvoie à la doc pour plus de détails.

Mise en place de la pagination



Bon, c'est bref et rapide, mais je l'affiche tout de même. Je ne la mettrai plus dans la suite du tutoriel. Et, je préviens, il n'y a pas l'utilisation de fonctions qui permettent de mettre trois petits points à la place des pages, je préfère faire simple et ne pas en mettre. Sachez tout de même qu'il y en a une ici.

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
 
// On calcule le nombre de pages en divisant le nombre de MP par le nombre de MP par page, et en prenant l'arrondi du résultat.
$nb_pages = ceil($nb_mp / $config['nb_mp_par_page']);
 
// On cherche à savoir s'il y a une page dans l'URL
if(!empty($_GET['page']))
   $page_actuelle = intval($_GET['page']);
else
   $page_actuelle = 1;
 
// Je préfère effectuer quelques vérifications, au cas où
if($page_actuelle < 1) // Si la page actuelle est inférieure à 1, alors on la met à 1
   $page_actuelle = 1;
if($page_actuelle > $nb_pages) // Si la page actuelle est supérieure au nombre de pages, alors on la met au nombre de pages
   $page_actuelle = $nb_pages;
 
// On calcule le numéro du premier MP pour le limit de la prochaine requête
$start = ($page_actuelle - 1) * $config['nb_mp_par_page'];
 
?>


Ceci étant fait, on peut passer à nos deux requêtes principales.

Les deux requêtes principales

La liste des MP



Bien, vous êtes prêts ?
Je pense que oui, mais je vais quand même décomposer la requête en plusieurs étapes plutôt que de tout vous balancer en vrac.

En premier lieu, on sélectionne les informations générales :

Code : SQL
1
2
3
SELECT mps.mp_id, mps.mp_titre
FROM mp_sujets mps
LIMIT ".$start.", ".$config['nb_max_mp'];


Donc là c'est vraiment le début, parce qu'en fait ça sélectionne tous les MP, de $start à $config['nb_max_mp'].
On va donc modifier la requête pour ne récupérer que les MP où le membre est participant. Pour ça, j'ai opté pour une sous-requête :

Code : SQL
1
2
3
4
SELECT mps.mp_id, mps.mp_titre
FROM mp_sujets mps
WHERE mps.mp_id IN (SELECT mp_id FROM mp_participants WHERE membre_id = '.$id_membre.' AND mp_supprimer = 0)
LIMIT ".$start.", ".$config['nb_max_mp'];


Eh oui, la sous-requête a son WHERE identique à notre COUNT de tout à l'heure. Mais ici, notre sous-requête récupère tous les id des MP auxquels le membre a accès. Ensuite, le mps.mp_id IN ... signifie qu'il faut récupérer les informations de tous les MP dont l'id est dans le résultat de la sous-requête. Je vous renvoie ici pour plus d'informations sur IN et dérivés (n'hésitez pas à lire les pages qui sont dans la "Section Navigation", elles traitent toutes des sous-requêtes, c'est toujours à bon à apprendre ;) ).

Bon, c'est bien mignon tout ça, mais on ne sait même pas combien de messages il y a dans chaque MP. Pour ça, pas très dur, un simple COUNT avec un WHERE, et l'on met le tout dans une nouvelle sous-requête :

Code : SQL
1
2
3
4
SELECT mps.mp_id, mps.mp_titre, (SELECT COUNT(*) FROM mp_messages mpm WHERE mpm.mp_id = mps.mp_id) AS nb_messages
FROM mp_sujets mps
WHERE mps.mp_id IN (SELECT mp_id FROM mp_participants WHERE membre_id = '.$id_membre.' AND mp_supprimer = 0)
LIMIT ".$start.", ".$config['nb_max_mp'];


Bon, pas très difficile.
N'oubliez pas de définir un alias pour la table, afin d'éviter d'avoir à mettre mp_id = mp_id :) .

Maintenant, il va falloir récupérer la date de la dernière réponse, ainsi que l'id et le pseudo de son auteur.
On va donc utiliser deux jointures qui peuvent sembler compliquées, mais qui sont extrêmement simples. Je vous affiche la requête, et je vous explique tout ensuite.

Code : SQL
1
2
3
4
5
6
SELECT mps.mp_id, mps.mp_titre, (SELECT COUNT(*) FROM mp_messages mpm WHERE mpm.mp_id = mps.mp_id) AS nb_messages
FROM mp_sujets mps
LEFT JOIN mp_messages mpm2 ON mpm2.mess_temps = (SELECT MAX(mpm3.mess_temps) FROM mp_messages mpm3 WHERE mpm3.mp_id = mps.mp_id)
LEFT JOIN membres m ON m.membre_id = mpm2.membre_id
WHERE mps.mp_id IN (SELECT mp_id FROM mp_participants WHERE membre_id = '.$id_membre.' AND mp_supprimer = 0)
LIMIT ".$start.", ".$config['nb_max_mp'];


Bon, faut s'accrocher un peu, là. ^^
On va commencer par la première jointure - le premier LEFT JOIN, si vous préférez.
On demande donc à joindre la table mp_messages. Mais il faut une condition à la jointure, qui est ici notre sous-requête. Cette dernière sélectionne la date maximale dans les messages, mais pas dans n'importe lesquels : grâce au WHERE, on précise bien qu'on veut sélectionner la plus grande date pour le MP que l'on traite actuellement.
Pour arriver à visualiser, imaginez que vous n'avez qu'un MP. Eh bien la sous-requête sélectionne la date la plus grande des messages de ce MP. Là c'est pareil, mais ça le fait plusieurs fois, pour chaque MP concerné.
Ainsi, notre jointure prend les informations du dernier message du MP !
Ensuite, il suffit de faire une autre jointure, sur la table membres, avec une condition simple : on joint de manière à ce que le membre soit l'auteur du dernier message.

Vous avez bien compris ?
Si oui, il suffit maintenant de rajouter les informations qui nous intéressent dans la liste de sélection.

Code : SQL
1
2
3
4
5
6
SELECT mps.mp_id, mps.mp_titre, (SELECT COUNT(*) FROM mp_messages mpm WHERE mpm.mp_id = mps.mp_id) AS nb_messages, m.membre_id AS auteur_id_dern_rep, m.membre_pseudo AS auteur_dern_rep, DATE_FORMAT(mpm.mess_temps, "%e %c %Y à %kh%i") AS date_dern_rep
FROM mp_sujets mps
LEFT JOIN mp_messages mpm2 ON mpm2.mess_temps = (SELECT MAX(mpm3.mess_temps) FROM mp_messages mpm2 WHERE mpm3.mp_id = mps.mp_id)
LEFT JOIN membres m ON m.membre_id = mpm2.membre_id
WHERE mps.mp_id IN (SELECT mp_id FROM mp_participants WHERE membre_id = '.$id_membre.' AND mp_supprimer = 0)
LIMIT ".$start.", ".$config['nb_max_mp'];


La grosse nouveauté, c'est la fonction DATE_FORMAT, qui permet de formater notre datetime comme nous le voulons. C'est comme date() en PHP. Allez jeter un oeil à la liste des fonctions de dates et heures avec MySQL, je suis sûr que vous serez vite convaincus d'opter pour ce système.

Bon, je vous rassure, la requête est quasiment finie.
Il ne nous reste plus qu'à ranger les MP par l'ordre décroissant de la date de dernière réponse.

Code : SQL
1
2
3
4
5
6
7
SELECT mps.mp_id, mps.mp_titre, (SELECT COUNT(*) FROM mp_messages mpm WHERE mpm.mp_id = mps.mp_id) AS nb_messages, m.membre_id AS auteur_id_dern_rep, m.membre_pseudo AS auteur_dern_rep, DATE_FORMAT(mpm.mess_temps, "%e %c %Y à %kh%i") AS date_dern_rep
FROM mp_sujets mps
LEFT JOIN mp_messages mpm2 ON mpm2.mess_temps = (SELECT MAX(mpm3.mess_temps) FROM mp_messages mpm2 WHERE mpm3.mp_id = mps.mp_id)
LEFT JOIN membres m ON m.membre_id = mpm2.membre_id
WHERE mps.mp_id IN (SELECT mp_id FROM mp_participants WHERE membre_id = '.$id_membre.' AND mp_supprimer = 0)
ORDER BY mpm2.mess_temps DESC
LIMIT ".$start.", ".$config['nb_max_mp'];


Bien, il ne reste plus qu'à mettre tout ça dans un array.
Car non, on ne va pas faire une boucle et tout afficher maintenant. Il manque la liste des participants à récupérer. Donc on met tout dans un array, et ensuite on fera une boucle sur le tableau pour pouvoir afficher.

Tant qu'on y est, on va déclarer une variable qui contiendra la liste des id des MP. Vous comprendrez après pourquoi.

Donc voilà le code qu'il faut créer pour tout enregistrer dans un array et créer la chaîne dont je parlais :

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
 
$liste_mp_id = ''; // Contiendra la liste des id des MP, séparés
$liste_mp = array(); // On crée le tableau qui va contenir la liste de nos MP
 
$sql = 'SELECT mps.mp_id, mps.mp_titre, (SELECT COUNT(*) FROM mp_messages mpm WHERE mpm.mp_id = mps.mp_id) AS nb_messages, m.membre_id AS auteur_id_dern_rep, m.membre_pseudo AS auteur_dern_rep, DATE_FORMAT(mpm.mess_temps, "%e %c %Y à %kh%i") AS date_dern_rep
FROM mp_sujets mps
LEFT JOIN mp_messages mpm2 ON mpm2.mess_temps = (SELECT MAX(mpm3.mess_temps) FROM mp_messages mpm2 WHERE mpm3.mp_id = mps.mp_id)
LEFT JOIN membres m ON m.membre_id = mpm2.membre_id
WHERE mps.mp_id IN (SELECT mp_id FROM mp_participants WHERE membre_id = '.$id_membre.' AND mp_supprimer = 0)
ORDER BY mpm2.mess_temps DESC
LIMIT '.$start.', '.$config['nb_max_mp'];
$requete = mysql_query($sql) or die(mysql_error());
 
while($row = mysql_fetch_row($requete)) // On fait une boucle de chaque MP
{
   $liste_mp = $row; // On met toutes nos données dans le tableau
   $liste_mp_id = (!empty($liste_mp_id) ? ', ' : '').$row['mp_id']; // On insère l'id du MP dans la liste
}
mysql_free_result($requete); // Permet de libérer de la mémoire, au cas où ^^
 
?>


Ça y est, on a un tableau contenant toutes les infos de nos MP ; on peut maintenant récupérer la liste des participants !

La liste des participants



Pour récupérer la liste des participants, ça ne va pas être trop dur. On aurait pu faire une requête qui aurait tout pris dans la BDD, comme ça on aurait eu les participants de nos conversations... mais aussi de celles dont on ne fait pas partie. C'est là que va entrer en jeu $liste_mp_id. On va récupérer les participants dont la conversation fait partie de l'ensemble des id que l'on avait tout à l'heure.
Pour cela, on va à nouveau utiliser IN.

Code : SQL
1
2
3
4
5
SELECT mp_id, mpp.membre_id, m.membre_pseudo, mpp_lu
FROM mp_participants mpp
LEFT JOIN membres m ON m.membre_id = mpp.membre_id
WHERE mp_id IN ('.$liste_mp_id.')
ORDER BY mp_id, username ASC';


Donc voilà, simple et efficace : on récupère l'id du MP concerné (vous allez comprendre de suite), le pseudo ainsi que l'id du membre, s'il l'a lu ou pas, et on classe le tout par id de MP, et ensuite par pseudo.

À nouveau, on va tout mettre dans un tableau, que l'on traitera juste après.

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<?php
 
$liste_participants = array();
 
$sql = 'SELECT mp_id, mpp.membre_id, m.membre_pseudo, mpp_lu
FROM mp_participants mpp
LEFT JOIN membres m ON m.membre_id = mpp.user_id
WHERE mp_id IN ('.$liste_mp_id.')
ORDER BY mp_id, username ASC';
$requete = mysql_query($sql) or die(mysql_error());
        
while($row = mysql_fetch_row($requete))
{
   $liste_participants[$row['mp_id']][$row['membre_id']]['pseudo'] = $row['membre_pseudo'];
   $liste_participants[$row['mp_id']][$row['membre_id']]['lu'] = $row['mpp_lu'];
   // On a inséré les données sur le membre
}
mysql_free_result($requete);
 
?>


Ce coup-ci, notre tableau est plus complexe. J'ai mis mp_id comme clé du tableau et aussi l'id du membre.
Nous avons donc ceci au final :

Code : Autre
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Array
(
   [1] => Array
      (
         [2] => Array
            (
               [pseudo] => nobodylistening
               [lu] => 1
            )
 
         [4] => Array
            (
               [pseudo] => Membre n°4
               [lu] => 1
            )
 
         [3] => Array
            (
               [pseudo] => Membre n°3
               [lu] => 0
            )
      )
 
   [2] => Array
      (
         [2] => Array
            (
               [pseudo] => nobodylistening
               [lu] => 0
            )
 
         [3] => Array
            (
               [pseudo] => Membre n°3
               [lu] => 1
            )
      )
)


Et cela, autant de fois qu'il y a de MP.
Et, grâce à cela, on va pouvoir afficher sans souci. :)

Traitement des données

Ça aura été long et laborieux, mais nous y sommes arrivés. On a enfin pouvoir afficher les données.
Par contre, je ne vous donnerai aucun code fini. Je vais vous donner des codes pour traiter la liste et vous montrer comment l'afficher, mais rien de plus. Vous êtes assez grands pour le faire, je pense. :D

On va commencer par lister les MP, en faisant une boucle sur liste_mp.
Mais bon, les boucles, ce n'est pas pratique comparé à foreach.

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<table id="liste_mp">
<?php
 
foreach($liste_mp as $mp) // foreach parcourt tout le tableau en donnant les infos dans $mp
{
   echo '<tr>';
 
   if($liste_participants[$mp['mp_id']][$id_membre]['lu'] == 0) // Si le membre qui visite la page a déjà lu le topic
      echo '<td>Non lu</lu>';
   else
      echo '<td>Lu</td>';
 
   echo '<td><a href="lire.php?id_mp='.$mp['mp_id'].'" title="Lire le MP">'.htmlspecialchars(stripslashes($mp['titre'])).'</a></td>'; // Un lien vers la lecture du MP
   echo '<td>'.$mp['nb_messages'].'</td>'; // On écrit le nombre de messages
 
   $nb_participants = count($liste_participants[$mp['mp_id']]) - 1; // On compte le nombre de participants, auquel on enlève 1, le membre qui est sur la page
   
   // Maintenant, on s'occuper d'afficher la liste des participants
   echo '<td>';
   foreach($liste_participants[$mp['mp_id']] as $id_participant => $element)
   {
      if(($nb_participants > 1 AND $id_participant != $id_membre) OR $nb_participants == 1) // Si l'id du participant est différent de celui du membre sur la page et s'il y a plus d'un participant, ou bien s'il n'y a qu'un participant 
      {
         // On cherche à savoir si le participant a lu ou non le MP
         if($element['lu'] == 0)
            echo 'Non lu';
         else
            echo 'Lu';
 
          echo htmlspecialchars(stripslashes($element['pseudo'])).'<br />'; // On écrit le pseudo du membre
      }
   }
   echo '</td>';
 
   // On écrit les infos sur la dernière réponse
   echo '<td>Dernier message le '.$mp['date_dern_rep'].'<br />
      Par '.htmlspecialchars(stripslashes($mp['auteur_dern_rep'])).'</td>';
}
 
?>
</table>


Eh bien, ça fait un bon petit bout de code. ^^
Je vais juste reprendre ceci :

Code : PHP
1
2
3
4
5
6
7
8
<?php
 
if($liste_participants[$mp['mp_id']][$id_membre]['lu'] == 0) // Si le membre qui visite la page a déjà lu le topic
      echo '<td>Non lu</lu>';
   else
      echo '<td>Lu</td>';
 
?>


Vu que $liste_participant est du genre [id_mp][id_membre][lu], on peut savoir si le membre a déjà lu le topic en mettant
[id du MP][id du membre ($id_membre)][lu].


Et aussi ce passage :

Code : PHP
1
<?php if(($nb_participants > 1 AND $id_participant != $id_membre) OR $nb_participants == 1) ?>


En clair, s'il n'y a qu'un participant, c'est que c'est le membre lui-même, donc on l'affiche. Sinon, s'il y a plus d'un participant, on n'affiche pas le membre qui est sur la page, car il sait qu'il y participe. :D

Tout le reste me semble plutôt clair.
On pourrait améliorer cette page en mettant la pagination pour le MP (pas très dur à faire, il suffit de diviser le nombre de messages du MP par le nombre maximum de messages par MP), un lien vers le profil du membre, une image au lieu du Lu / Non lu. À vous de jouer. ;)

Eh bien voilà, vous venez d'afficher la liste de vos MP.
Maintenant, on va pouvoir faire la page Lire un MP. :)
Chapitre précédent Sommaire Chapitre suivant
Retour en haut Retour en haut


Créé : le 08/09/2007 à 08:04:36
Modifié : le 22/08/2008 à 15:52:18
Avancement : 100%
Licence : Copie non autorisée

7 commentaires

Changer de design | En savoir plus | Plan du site | Politique d'accessibilité | Règles | RSS tutoriels | RSS news
Édité par Simple IT SARL : Nous contacter | Notre blog | Revue de presse | Publicité

Y'a plus rien à lire, faut remonter maintenant !

Hébergement web - Correction de tutoriels - Créer un site
Vous souhaitez apparaître ici ? Contactez-nous.

Nombre de connectés 456 Zéros connectés | Requêtes SQL 8 requêtes | Temps de génération de la page : Total (SQL) 0.0476s (0.0363s)