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)
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_participants où
membre_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 : PHP1
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.
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 : SQL1
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 : SQL1
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 : SQL1
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 : SQL1
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 : SQL1
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 : SQL1
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 : SQL1
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 : Autre1
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.
Ç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.
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 : PHP1
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 : PHP1 | <?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.
Tout le reste me semble plutôt clair.