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 > Créer son forum de toutes pièces > Et plus > Quelques fonctions en plus > Lecture du tutoriel

Quelques fonctions en plus

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 : General Vans
Note : 18 / 20 (9 votes)
Visualisations : 10 287

Plus d'informations Plus d'informations
Cette partie a été créée pour ceux qui désirent améliorer leur forum, mais qui ne savent pas trop par où commencer. Je vais donc indiquer quelques fonctionnalités supplémentaires qu'il est facile de mettre en place. Bien entendu, il ne s'agit que de quelques pistes, c'est à vous de personnaliser votre forum (sinon, ça ne sert à rien de le faire soi-même).

Le premier système que nous allons voir est quasiment indispensable sur un forum : il s'agit du fameux système lu / non-lu concernant les messages.

Le deuxième système est celui de l'affichage des membres / non-membres (qui est en ligne ?).
Sommaire du chapitre :
Icône du chapitre
Chapitre précédent Sommaire Chapitre suivant

Système lu / non-lu

Avant de commencer, j'aimerais insister sur le fait qu'il existe un très bon tuto sur la question ici-même : lien.

Mais ici, on va voir comment faire un système plus à la SDZ, avec possibilité de se rendre au dernier message non-lu.

Comment on s'y prend ?



Pour faire un système de ce type, on va avoir besoin d'une nouvelle table, qui s'appelle forum_topic_view ( :lol: ) ; voici comment elle se compose :


Vous pouvez comprendre qu'elle va servir à relier les id de chaque membre avec les topics qu'ils ont consultés, mais elle peut aussi faire plein d'autres choses qu'on verra en leur temps ^^ .

Voici la requête pour créer la table :
Code : SQL
1
2
3
4
5
6
7
8
CREATE TABLE `forum_topic_view` (
`tv_id` INT( 11 ) NOT NULL ,
`tv_topic_id` INT( 11 ) NOT NULL ,
`tv_forum_id` INT( 11 ) NOT NULL ,
`tv_post_id` INT( 11 ) NOT NULL ,
`tv_poste` ENUM( '0', '1' ) NOT NULL,
PRIMARY KEY  (`tv_id`,`tv_topic_id`)
) TYPE = MYISAM ;


Ensuite, il va vous falloir 5 images,
une pour les messages non-lus,
une pour les messages lus dans un topic où le membre a posté,
une pour les messages non-lus dans un topic où le membre a posté,
une pour les messages non-lus dans un topic que le membre a consulté
et une pour les messages déjà lus.

Je les ai appelées respectivement :
message_non_lu.gif Image utilisateur
messagep_lu.gif Image utilisateur
messagep_non_lu.gif Image utilisateur
messagec_non_lus.gif Image utilisateur
message.gif Image utilisateur


Voici pour les correspondances avec le SDZ, on peut remarquer que le site ne fait pas de distinction entre message simple non lu et message consulté non lu (en réalité une petite flèche est ajoutée nous permettant d'aller au dernier post lu).

Modification des pages php (Information)



Bon. Jusqu'ici tout va bien, c'est maintenant qu'il va falloir s'accrocher un peu ^^ . On va tout d'abord s'occuper de la récupération d'informations, puis on verra l'affichage ensuite.

Page voirtopic.php



Donc, il faut ouvrir la page voirtopic.php : c'est en visitant celle-ci que le membre consulte un topic, et on va tout simplement faire une requête qui envoie le résultat à savoir :
- l'id du membre qu'on obtient avec $_SESSION['id'],
- l'id du topic qui est obtenu en GET (elle est contenu dans la variable $topic)
- et enfin, l'id du dernier message qui est connue grâce à la requête placée au début, et qui récupère des infos sur le topic, la variable est donc $data1['topic_last_post'].

2 remarques :
1/ il faut s'assurer que le membre est bien connecté avant de faire cette requête ; le mieux est de la placer dans le premier if qui affiche les infos, selon que le visiteur est un membre ou un invité.

2/ La requête initiale (telle qu'on l'a écrite dans les chapitres précédents) ne sélectionne pas la valeur de topic_last_post, il faudra donc penser à l'ajouter.


Mais ce n'est pas tout : il faut également regarder s'il n'existe pas déjà une entrée avec ce topic et ce membre ; si c'est le cas, c'est-à-dire si le membre a déjà visité le topic, il faudra simplement mettre à jour la valeur du champ tv_post_id.

Voici le script :

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<?
//Topic déjà consulté ?
$nbr_vu = mysql_result(mysql_query("SELECT COUNT(*) FROM forum_topic_view
WHERE tv_topic_id = '".$topic."' AND tv_id = '".intval($_SESSION['id'])."'"), 0);
if ($nbr_vu == 0) //Si c'est la première fois on insère une ligne entière
{
        mysql_query('INSERT INTO forum_topic_view 
        (tv_id, tv_topic_id, tv_forum_id, tv_post_id)
        VALUES ('.intval($_SESSION['id']).', '.$topic.', '.$data1['forum_id'].', '.$data1['topic_last_post'].')');
}
else //Sinon, on met simplement à jour
{
        mysql_query('UPDATE forum_topic_view SET tv_post_id = 
        '.$data1['topic_last_post'].' WHERE tv_topic_id = '.$topic.' 
        AND tv_id = '.intval($_SESSION['id']));
}
?>


Il est inutile de s'occuper ici du champ tv_poste, il reste à 0, mais on se chargera de son cas dans 2 secondes ^^ .

Page postok.php



Sur cette page, il va falloir faire deux choses : si on crée un nouveau topic, il faudra ajouter une ligne dans la table forum_topic_view, exactement comme on vient de le faire. Par contre, si on envoie une réponse, il faudra mettre à jour cette table, on changera ainsi la valeur de tv_post_id et tv_poste.

Donc, dans la partie du switch traitant d'un nouveau topic, vous devez placer, juste avant le echo, le code suivant :

Page : postok.php

Code : PHP
1
2
3
4
5
6
<?
//On ajoute une ligne dans la table forum_topic_view
mysql_query('INSERT INTO forum_topic_view 
(tv_id, tv_topic_id, tv_forum_id, tv_post_id, tv_poste) 
VALUES('.intval($_SESSION['id']).', '.$nouveautopic.', '.$forum.', '.$nouveaupost.', "1")');
?>


Et de même, dans la partie traitant des réponses :

Code : PHP
1
2
3
4
5
6
<?
//On update la table forum_topic_view
mysql_query('UPDATE forum_topic_view 
SET tv_post_id = '.$nouveaupost.', tv_poste = "1"
WHERE tv_id = '.intval($_SESSION['id']).' AND tv_topic_id = '.$topic.'');
?>


Si vous ne vous souvenez plus des variables utilisées, regardez un coup votre code, ou alors reprenez le chapitre en question. Vous voyez que tout est déjà en place : en fait, il ne reste plus qu'à appliquer ce qu'on a dit plus haut :) .

Bon, c'en est terminé pour la première partie ; on va maintenant passer à la gestion de l'affichage, qui est un peu plus tordue.

Modification des pages php (Affichage)



Page voirforum.php



Alors, j'espère que vous êtes prêts, parce que la suite va demander un peu plus d'attention.
Déjà ouvrez la page voirforum.php : il va falloir modifier les deux requêtes qui listent les sujets, afin d'y associer la table forum_topic_view.
Pour cela, une jointure sera très utile : on pourra récupérer la valeur de tv_id et de tv_topic_id, et tout se déroulera parfaitement ; mais il ne faut pas oublier une chose : un visiteur n'est pas forcément connecté, et c'est là que ça se corse un peu, il va falloir discerner les cas une fois de plus.

En fait, la requête va être modifiée à deux endroits, selon qu'on est connecté ou non (pour la sélection des champs et pour la jointure) ; en effet, si on est un simple invité, inutile d'inclure la table forum_topic_view, puisqu'on marquera alors tous les messages comme déjà lus.
Donc, ce que l'on va faire, c'est créer deux variables : elles contiendront une portion de la requête si le membre est connecté, et rien si ce n'est pas le cas.

J'imagine que c'est difficile à comprendre avec des mots, alors je vous montre la première partie du script : elle se trouve juste avant la première grosse requête qui liste les annonces :) .

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<?
if (isset($_SESSION['id'])) 
{
//Premièrement, sélection des champs
$add1 = ',tv_id, tv_post_id, tv_poste'; 
//Deuxièmement, jointure
$add2 = 'LEFT JOIN forum_topic_view 
ON forum_topic.topic_id = forum_topic_view.tv_topic_id AND forum_topic_view.tv_id = '.intval($_SESSION['id']);
}
?>


Les variables $add1 et $add2 contiennent donc une partie de la requête : s'ils ne sont pas renseignés, alors la jointure ne se fera pas, et on n'y verra que du feu ^^ .

J'en profite pour expliquer un peu cette ligne :

Code : SQL
1
ON forum_topic.topic_id = forum_topic_view.tv_topic_id AND forum_topic_view.tv_id = blablabla


En fait, on veut inclure la table forum_topic_view, mais pas entièrement ; sinon, lors de l'affichage, on aurait sur la page autant de fois un topic qu'il a été vu par les membres, ce qui n'est pas forcément très intéressant, quand on y pense ^^ . Donc, on ajoute une condition sur le ON, qui récupère uniquement les lignes de la table qui nous intéressent, à savoir celles qui concernent le membre en question.

Pour la suite, il va falloir reprendre la requête de cette façon :

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<?
$requete3 = mysql_query('SELECT forum_topic.topic_id, topic_titre, topic_createur, topic_vu, topic_post, topic_time, topic_last_post, topic_locked,
Mb.membre_pseudo AS membre_pseudo_createur, post_id, post_createur, post_time, Ma.membre_pseudo AS membre_pseudo_last_posteur 
'.$add1.' 
FROM forum_topic
LEFT JOIN forum_membres Mb ON Mb.membre_id = forum_topic.topic_createur
LEFT JOIN forum_post ON forum_topic.topic_last_post = forum_post.post_id
LEFT JOIN forum_membres Ma ON Ma.membre_id = forum_post.post_createur  
'.$add2.'
WHERE topic_genre = "Annonce" AND forum_topic.forum_id = "'.$forum.'" ORDER BY topic_last_post DESC');
?>


Ainsi, il n'y aura plus d'erreurs si vous visitez la page en tant qu'invité !
Je vous laisse faire de même pour les topics normaux.

Passons à présent à la sélection de l'icône à afficher. Il s'agit d'un gros enchevêtrement de if / else, donc il ne faut surtout pas perdre de vue ce que l'on fait.

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
<?
//Gestion de l'image à afficher
if (isset($_SESSION['id'])) // Si le membre est connecté
{
   if ($data3['tv_id'] == $_SESSION['id']) //S'il a lu le topic
   {
      if ($data3['tv_poste'] == '0') // S'il n'a pas posté
      {
         if ($data3['tv_post_id'] == $data3['topic_last_post']) //S'il n'y a pas de nouveau message
         {
           $ico_mess = 'message.gif';
         }
         else
         {
           $ico_mess = 'messagec_non_lus.gif'; //S'il y a un nouveau message
         }
      }
      else // S'il a  posté
      {
         if ($data3['tv_post_id'] == $data3['topic_last_post']) //S'il n'y a pas de nouveau message
         {
            $ico_mess = 'messagep_lu.gif';
         }
         else //S'il y a un nouveau message
         {
            $ico_mess = 'messagep_non_lu.gif';
         }
       }
   }
   else //S'il n'a pas lu le topic
   {
   $ico_mess = 'message_non_lu.gif';
   }
} //S'il n'est pas connecté
else
{
$ico_mess = 'message.gif';
}
?>


Piuf, ça fait des cas différents, mais au moins tout est pris en compte. J'espère que les commentaires vous ont aidés à comprendre comment ça fonctionne ; sinon, essayez avec des topics, et vous verrez que ça marche ^^ .

Il ne vous reste maintenant plus qu'à afficher la valeur de $ico_mess de la façon suivante :

Code : PHP
1
echo'<tr><td><img src="./images/'.$ico_mess.'"></td>';


Et ce, à la place de l'ancien echo, qui faisait simplement

Code : PHP
1
echo'<tr><td><img src="./images/annonce.gif"></td>';


N'hésitez surtout pas à relire le code, et à essayer de le refaire (d'ailleurs, il faut que vos le refassiez pour la liste des topics "normaux" ; je rappelle qu'ici il ne s'agit que des annonces).


Maintenant, comme sur le SDZ, vous pouvez repérer plus facilement les topics où vous avez posté par rapport à ceux que vous avez simplement consultés.

Page index.php



Bon bah pour la page d'index, c'est la même affaire, je vais donc vous laisser vous débrouiller un peu seuls. La seule différence, c'est que cette fois on utilise le dernier post du forum, et non pas du topic. Il faut utiliser le champ tv_forum_id tout simplement.
Donc, une fois la condition faite, vous entrez le résultat dans la variable $ico_mess, et puis le tour est joué : il vous suffit de recopier la série de conditions !

Faire des liens sympas



Le gros avantage de cette méthode est qu'il est possible de faire, encore une fois comme sur le SdZ, des liens qui nous listent directement les topics où l'on a posté, ceux que l'on a visités, etc.
Donc, n'hésitez pas à vous amuser à en faire : non seulement ça sera un bon entraînement si vous avez compris la méthode, mais c'est toujours un plus pour les visiteurs (personnellement, j'utilise très souvent cette option et je suis très content qu'elle existe :) ).

Si vous avez un peu digéré, on va passer à une partie plus tranquille qui est la réalisation de la fonction "Qui est en ligne ?".

Qui est en ligne ?

Dans cette partie, nous allons voir comment afficher la liste de tous les membres connectés.

Ce système n'est pas très compliqué à réaliser : au final, il suffit d'entrer dans une table l'id du membre et sa date de dernière activité. En fait, c'est assez connu comme méthode, tellement qu'elle se trouve même dans les cours de M@teo21, ici !.

Mais nous, la différence, c'est qu'on veut également afficher le nom des personnes connectées et le nombre de visiteurs.

La base de données



Bah ça va, on la connaît ta table, elle est dans le tuto de M@teo !


Oui, mais pas seulement : en effet, comme on veut également compter le nombre de membres et afficher leur nom, il va falloir ajouter un champ à la table qui contient les id des visiteurs. S'ils ne sont pas connectés, celles-ci vaudront 0, sinon, on pourra obtenir leur nom avec une jointure SQL.

Voici donc la requête pour créer la table :

Code : SQL
1
2
3
4
5
6
CREATE TABLE `forum_whosonline` (
  `online_id` int(11) NOT NULL,
  `online_time` int(11) NOT NULL,
  `online_ip` int(15) NOT NULL,
  PRIMARY KEY  (`online_ip`)
) ENGINE=MyISAM


Contrairement à M@teo, j'utilise un type INT pour l'adresse IP : on pourra alors la convertir avant l'entrée, grâce à la fonction ip2long.


Un petit boulot pour vous



Bon bah, c'est à vous de jouer cette fois, je ne vais pas vous demander un boulot monstre non plus, mais je tiens à vous garder éveillés, et à éviter les bêtes copier / coller.
Donc, vous allez insérer le code suivant ; vous pouvez le mettre dans la page debut.php, néanmoins, je rappelle que dans celle-ci, la connexion à la base de données n'est pas encore effectuée : donc, il peut être préférable d'utiliser une nouvelle page à inclure.

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<?
//Création des variables
$ip = ip2long($_SERVER['REMOTE_ADDR']);
if (!isset($_SESSION['id'])) $id=0;
else $id = intval($_SESSION['id']);

//Requête
mysql_query('INSERT INTO forum_whosonline VALUES('.$id.', '.time().','.$ip.')
ON DUPLICATE KEY UPDATE
online_time = '.time().' , online_id = '.$id.'');
?>


Cette méthode est la même que celle de M@teo, mais en plus rapide : en effet, on ne cherche pas à savoir si l'ip se trouve déjà dans la table, on l'écrase si c'est le cas, et on met à jour le temps, et on ajoute une ligne si ce n'est pas le cas. C'est à ça que sert le DUPLICATE KEY UPDATE, et c'est aussi pour cela qu'on a mis une clé primaire sur l'ip.

Ensuite, de la même manière, il va falloir supprimer les entrées trop vieilles : pour cela, à la suite de ce que vous venez d'écrire, mettez ceci.

Code : PHP
1
2
3
4
<?
$time_max = time() - (60 * 5);
mysql_query('DELETE FROM forum_whosonline WHERE online_time < '.$time_max);
?>


Jusqu'ici pas de problème, la suite devrait passer tranquillement aussi ^^ .

Affichage



Bon, il ne reste plus qu'à afficher tout ça sur le pied de page de la page d'index (ou le pied de page commun à chaque page, c'est à vous de voir :) ).

Tout d'abord on va compter un peu : le total des personnes sur le site est la somme visiteurs + membres ; il va donc falloir traduire cela en php.

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<?
//Initialisation de la variable
$count_online = 0;

//Décompte des visiteurs
$count_visiteurs= mysql_result(mysql_query('SELECT COUNT(*) AS nbr_visiteurs FROM forum_whosonline WHERE online_id = 0'),0);

//Décompte des membres
$time_max = time() - (60 * 5);
$requete_count_membres = mysql_query('SELECT membre_id, membre_pseudo 
FROM forum_whosonline
LEFT JOIN forum_membres ON membre_id = online_id
WHERE online_time > '.$time_max);
$count_membres = mysql_num_rows($requete_count_membres);

$count_online = $count_visiteurs + $count_membres;

echo '<p>Il y a '.$count_online.' connectés ('.$count_membres.' membres et '.$count_visiteurs.' invités)';
?>


Dans ce code, on fait deux requêtes : une pour les visiteurs, et une pour les membres connectés ; on obtient ainsi leur nombre, mais également des infos supplémentaires pour ces derniers : leur pseudo. On peut ainsi afficher la liste des personnes en lignes.

Pour afficher la liste, j'utilise une méthode nouvelle dans ce tuto : en fait, on stocke le texte à afficher dans une variable, à chaque fois on va ajouter le nouveau nom, suivi d'une virgule. A la fin, on enlève la dernière virgule (sinon, ça fait moche une virgule toute seule avec rien après ^^ ) grâce à la fonction substr.

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<?
$texte_a_afficher = "<br />Liste des personnes en ligne : ";
while ($data_count_membres = mysql_fetch_assoc($requete_count_membres))
{
$texte_a_afficher .= '<a href="./voirprofil.php?m='.$data_count_membres['membre_id'].'&amp;action=consulter">
'.stripslashes(htmlspecialchars($data_count_membres['membre_pseudo'])).'</a> ,';
}
$texte_a_afficher = substr($texte_a_afficher, 0, -1);
echo $texte_a_afficher.'</p>';
?>


Et le tour est joué, il ne vous reste plus qu'à tester ça, et à l'améliorer comme ça vous amuse. :)

Hey ! Si je me déconnecte de mon compte je suis encore affiché en ligne ! Ca marche pas ton truc !


En effet c'est un problème, lors de la déconnexion le membre est encore affiché en ligne pendant 5 minutes.
Donc il faut régler ça n'est ce pas ? Et bah aucun soucis, ouvrez la page deconnexion.php et faites ceci :

Code : PHP
1
2
3
4
5
6
7
8
<?
session_start();
include("includes/identifiants.php");
mysql_connect($adresse, $nom, $motdepasse);
mysql_select_db($database);
mysql_query('DELETE FROM forum_whosonline WHERE online_id='.intval($_SESSION['id']));
session_destroy();
?>


A la place du beaucoup plus sobre :

Code : PHP
1
2
3
4
<?
session_start();
session_destroy();
?>


Voilà : pour le coup, c'est tout. :)

J'ai présenté deux fonctionnalités importantes d'un forum, mais ce ne sont pas les seules : par exemple, un système de recherche peut être très utile pour faire gagner du temps aux membres :) (à ce sujet, je vous conseille ce tuto).

Une remarque importante
: il existe une autre façon d'afficher les messages lus / non-lus, qui se base sur la date de dernière connexion du membre ; elle n'utilise donc pas de nouvelles tables. Si vous voulez en savoir plus, je vous envoie au tuto suivant.
Chapitre précédent Sommaire Chapitre suivant
Retour en haut Retour en haut


Créé : le 13/09/2006 à 19:48:41
Modifié : le 01/09/2008 à 23:08:45
Avancement : 100%
Licence : Creative Commons BY

14 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 85 Zéros connectés | Requêtes SQL 8 requêtes | Temps de génération de la page : Total (SQL) 0.0881s (0.0766s)