Aller au menu - Aller au contenu

Icône Quelques fonctions en plus

Avatar
Mise à jour : 30/11/2010
Difficulté : Facile Facile Creative Commons BY
4 145 visites depuis 7 jours, dont 97 sur ce chapitre classé 41/786
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 :
  • un champ tv_id qui contient l'id du membre
  • un champ tv_topic_id qui contient l'id du topic
  • un champ tv_post_id qui contient l'id du dernier post lu du topic
  • un champ tv_poste, qui contient 0 ou 1 si on a posté ou non dans le topic.


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 $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 $data['topic_last_post'].


Pensez à vous assurer que le membre est bien connecté avant de faire cette requête


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
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php
//Topic déjà consulté ?
$query=$db->prepare('SELECT COUNT(*) FROM forum_topic_view WHERE tv_topic_id = :topic AND tv_id = :id');
$query->bindValue(':topic',$topic,PDO::PARAM_INT);
$query->bindValue(':id',$id,PDO::PARAM_INT);
$query->execute();
$nbr_vu=$query->fetchColumn();
$query->CloseCursor();
if ($nbr_vu == 0) //Si c'est la première fois on insère une ligne entière
{
    $query=$db->prepare('INSERT INTO forum_topic_view 
    (tv_id, tv_topic_id, tv_forum_id, tv_post_id)
    VALUES (:id, :topic, :forum, :last_post)');
    $query->bindValue(':id',$id,PDO::PARAM_INT);
    $query->bindValue(':topic',$topic,PDO::PARAM_INT);
    $query->bindValue(':forum',$forum,PDO::PARAM_INT);
    $query->bindValue(':last_post',$data['topic_last_post'],PDO::PARAM_INT);
    $query->execute();
    $query->CloseCursor();
      
}
else //Sinon, on met simplement à jour
{
    $query=$db->prepare('UPDATE forum_topic_view SET tv_post_id = :last_post 
    WHERE tv_topic_id = :topic 
    AND tv_id = :id');
    $query->bindValue(':last_post',$data['topic_last_post'],PDO::PARAM_INT);
    $query->bindValue(':topic',$topic,PDO::PARAM_INT);
    $query->bindValue(':id',$id,PDO::PARAM_INT);
    $query->execute();
    $query->CloseCursor();
}
?>


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
 7
 8
 9
10
11
12
13
<?php
//On ajoute une ligne dans la table forum_topic_view
$query=$db->prepare('INSERT INTO forum_topic_view 
(tv_id, tv_topic_id, tv_forum_id, tv_post_id, tv_poste) 
VALUES(:id, :topic, :forum, :post, :poste)');
$query->bindValue(':id',$id,PDO::PARAM_INT);
$query->bindValue(':topic',$nouveautopic,PDO::PARAM_INT);
$query->bindValue(':forum',$forum ,PDO::PARAM_INT);
$query->bindValue(':post',$nouveaupost,PDO::PARAM_INT);
$query->bindValue(':poste','1',PDO::PARAM_STR);
$query->execute();
$query->CloseCursor();
?>


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

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<?php
//On update la table forum_topic_view
$query=$db->prepare('UPDATE forum_topic_view 
SET tv_post_id = :post, tv_poste = :poste
WHERE tv_id = :id AND tv_topic_id = :topic')
$query->bindValue(':post',$nouveaupost,PDO::PARAM_INT);
$query->bindValue(':poste','1',PDO::PARAM_STR);
$query->bindValue(':id',$id,PDO::PARAM_INT);
$query->bindValue(':topic',$topic,PDO::PARAM_INT);
$query->execute();
$query->CloseCursor();
?>


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
11
12
<?php
$add1='';
$add2='';
if ($id!=0) //on est connecté 
{
//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 = :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
12
13
14
15
<?php
$query=$db->prepare('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_createur, post_time, Ma.membre_pseudo AS membre_pseudo_last_posteur, 
'.$add1.' post_id 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');
$query->bindValue(':forum',$forum,PDO::PARAM_INT);
if ($id!=0) $query->bindValue(':id',$id,PDO::PARAM_INT);
$query->execute();

?>


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
<?php
//Gestion de l'image à afficher
if (!empty($id)) // Si le membre est connecté
{
    if ($data['tv_id'] == $id) //S'il a lu le topic
    {
        if ($data['tv_poste'] == '0') // S'il n'a pas posté
        {
            if ($data['tv_post_id'] == $data['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 ($data['tv_post_id'] == $data['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.

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<?php
//Création des variables
$ip = ip2long($_SERVER['REMOTE_ADDR']);

//Requête
$query=$db->prepare('INSERT INTO forum_whosonline VALUES(:id, :time,:ip)
ON DUPLICATE KEY UPDATE
online_time = :time , online_id = :id');
$query->bindValue(':id',$id,PDO::PARAM_INT);
$query->bindValue(':time',time(), PDO::PARAM_INT);
$query->bindValue(':ip', $ip, PDO::PARAM_INT);
$query->execute();
$query->CloseCursor();
?>


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
5
6
7
<?php
$time_max = time() - (60 * 5);
$query=$db->prepare('DELETE FROM forum_whosonline WHERE online_time < :timemax');
$query->bindValue(':timemax',$time_max, PDO::PARAM_INT);
$query->execute();
$query->CloseCursor();
?>


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.

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
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php
//Initialisation de la variable
$count_online = 0;

//Décompte des visiteurs
$count_visiteurs=$db->query('SELECT COUNT(*) AS nbr_visiteurs FROM forum_whosonline WHERE online_id = 0')->fetchColumn();
$query->CloseCursor();

//Décompte des membres
$texte_a_afficher = "<br />Liste des personnes en ligne : ";
$time_max = time() - (60 * 5);
$query=$db->prepare('SELECT membre_id, membre_pseudo 
FROM forum_whosonline
LEFT JOIN forum_membres ON online_id = membre_id
WHERE online_time > :timemax AND online_id <> 0');
$query->bindValue(':timemax',$time_max, PDO::PARAM_INT);
$query->execute();
$count_membres=0;
while ($data = $query->fetch())
{
	$count_membres ++;
	$texte_a_afficher .= '<a href="./voirprofil.php?m='.$data['membre_id'].'&amp;action=consulter">
	'.stripslashes(htmlspecialchars($data['membre_pseudo'])).'</a> ,';
}

$texte_a_afficher = substr($texte_a_afficher, 0, -1);
$count_online = $count_visiteurs + $count_membres;
echo '<p>Il y a '.$count_online.' connectés ('.$count_membres.' membres et '.$count_visiteurs.' invités)';
echo $texte_a_afficher.'</p>';
$query->CloseCursor();
?>


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
 9
10
11
12
13
<?php
session_start();
$titre="Déconnexion";
include("includes/identifiants.php");
include("includes/debut.php");
include("includes/menu.php");
session_destroy();
$query=$db->prepare('DELETE FROM forum_whosonline WHERE online_id= :id');
$query->bindValue(':id',$id,PDO::PARAM_INT);
$query->execute();
$query->CloseCursor();

?>


A la place du beaucoup plus sobre :

Code : PHP
1
2
3
4
5
6
<?
session_start();
session_destroy();
include("includes/debut.php");
include("includes/menu.php");
?>


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

Partager

34 commentaires pour "Quelques fonctions en plus"
Note moyenne : 3.61 / 4 (348 votes)
Pseudo Commentaire
Hors ligne coolfarmer # Posté le 21/11/2011 à 01:37:05
Avatar

J'aimerais apporter mon aide à ceux qui sont confrontés au script Lu/Non-lu de la page d'index. En fait même avec mes 7 années d'expériences en programmation, j'avais de la difficulté avec cette partie, mais finalement c'est très simple quand on réfléchit et qu'on ne porte pas attention au tutoriel, car l'explication est TRÈS ambiguë.

Citation : Tutoriel
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.


Il faudrait préciser que le champ tv_forum_id ne sert absolument pas dans le choix de l'icône à afficher, elle sert seulement pour la condition dans le LEFT JOIN.

Pour ceux qui voudrait apporter une correction à leur script après bien-sûre avoir essayer eux-même de le faire, je proposes ma correction à moi avec quelques ajouts effectués grâce aux commentaires plus haut.

Secret (cliquez pour afficher)

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
<?php
// Système LUS/NON-LUS
$add1 = '';
$add2 = '';
			
if ($_SESSION['uniqueID'] != 0) // On est connecté 
{
	// Premièrement, sélection des champs
	$add1 = 'tv_id, tv_topic_id, tv_forum_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.forum_id = forum_topic_view.tv_forum_id AND forum_topic_view.tv_id = :id';
				
}
			
$query = $db->prepare('SELECT cat_id, cat_nom, 
forum_forum.forum_id, forum_name, forum_last_post_id, forum_desc, forum_post, forum_topic, auth_view, forum_topic.topic_id,  forum_topic.topic_post, 
post_id, post_time, post_createur, pseudo AS membre_pseudo, 
' . $add1 . ' id AS membre_id 
FROM forum_categorie
LEFT JOIN forum_forum ON forum_categorie.cat_id = forum_forum.forum_cat_id
LEFT JOIN forum_post ON forum_post.post_id = forum_forum.forum_last_post_id
LEFT JOIN forum_topic ON forum_topic.topic_id = forum_post.topic_id
LEFT JOIN site_membres ON site_membres.id = forum_post.post_createur 
' . $add2 . '
WHERE auth_view <= :lvl 
ORDER BY cat_ordre, forum_ordre ASC');
$query->bindValue(':lvl',$lvl,PDO::PARAM_INT);if ($_SESSION['uniqueID'] != 0) $query->bindValue(':id',$_SESSION['uniqueID'],PDO::PARAM_INT);
$query->execute();
?>

<?php
// Gestion de l'image à afficher
if (!empty($_SESSION['uniqueID'])) // Si le membre est connecté
{
	// Si le forum est vide alors on affiche que le forum est lu
	if ($data['forum_post'] == '' OR $data['forum_post'] == NULL OR $data['forum_post'] == 0){
		$ico_mess = 'forum_read.gif';
	}
	else
	{
		if ($data['tv_id'] == $_SESSION['uniqueID']) // S'il a lu le topic
		{
			if ($data['tv_post_id'] == $data['forum_last_post_id']) // S'il n'y a pas de nouveau message
			{
				$ico_mess = 'forum_read.gif';
			}
			else
			{
				$ico_mess = 'forum_unread.gif'; // S'il y a un nouveau message
			}
		}
		else // S'il n'a pas lu le topic
		{
			$ico_mess = 'forum_unread.gif';
		}
	}
} // S'il n'est pas connecté
else
{
	$ico_mess = 'forum_read.gif';
}
?>



Bien-sûre, n'utiliser pas ma requête au complet car j'ai des variables propres à mes scripts à l'intérieur, mais servez-vous s'en pour établir une correction à votre script (surtout ou niveau de la section de l'affichage de l'icône où je penses c'est là que les zéros ont de la difficulté.

Projet-TP.com - La Simulation de Travaux Publics et Bâtiments!
Image utilisateur

Imaginez ... vous devenez propriétaire d'une entreprise de Bâtiment et de Travaux Publics! Vous devez réaliser des projets proposés par les communes de votre département, avec vitesse, efficacité et qualité vous aurez à réaliser ceux-ci dans les plus brefs délais ! C'est maintenant possible avec Projet-TP, gérez du mieux possible votre entreprise BTP afin de devenir l'un des plus grands entrepreneurs.
 
Connecté superzero3 # Posté le 30/11/2011 à 18:11:53
Je suis un superzero
Groupe : Bannis

Ma page index.php est comme ça :
Secret (cliquez pour afficher)
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
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
<?php
//Cette fonction doit être appelée avant tout code html
session_start();?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr">
    <head>
        <meta charset="iso-8859-1" />
		<link rel="stylesheet" media="screen" type="text/css" title="Style" href="../Style.css" />
		<script type="text/javascript" src="../jquery.js"></script>
        <title>Index du forum</title>
    </head>
    <body onload="menu(6);">
<div id="en_tete"><div id="en_tetes"><?php include("includes/en_tete.php")?></div></div></div>
	<div id="menu"> <div class="element_menu">
   <?php include("menu.php"); ?></div></div>
   <br />
   <div id="corps">

   
<?php
//On donne ensuite un titre à la page, puis on appelle notre fichier debut.php
$titre = "Index du forum";
include("includes/identifiants.php");
include("includes/debut.php");
include("includes/menu.php");
//Initialisation de deux variables
$totaldesmessages = 0;
$categorie = NULL;
echo'<i><p>Vous êtes ici : </i><a href = "./index.php">Index du forum</a></p><h1>Mon super forum</h1>';
//Cette requête permet d'obtenir tout sur le forum

// Système LUS/NON-LUS
$add1 = '';
$add2 = '';
			
if (!empty($id)) // On est connecté 
{
	// Premièrement, sélection des champs
	$add1 = 'tv_id, tv_topic_id, tv_forum_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.forum_id = forum_topic_view.tv_forum_id AND forum_topic_view.tv_id = :id';
				
}
			
$query = $db->prepare('SELECT cat_id, cat_nom, 
forum_forum.forum_id, forum_name, forum_last_post_id, forum_desc, forum_post, forum_topic, auth_view, forum_topic.topic_id,  forum_topic.topic_post, 
post_id, post_time, post_createur, pseudo AS membre_pseudo, 
' . $add1 . ' id AS membre_id 
FROM forum_categorie
LEFT JOIN forum_forum ON forum_categorie.cat_id = forum_forum.forum_cat_id
LEFT JOIN forum_post ON forum_post.post_id = forum_forum.forum_last_post_id
LEFT JOIN forum_topic ON forum_topic.topic_id = forum_post.topic_id
LEFT JOIN site_membres ON site_membres.id = forum_post.post_createur 
' . $add2 . '
WHERE auth_view <= :lvl 
ORDER BY cat_ordre, forum_ordre ASC');
$query->bindValue(':lvl',$lvl,PDO::PARAM_INT);if ($_SESSION['uniqueID'] != 0) $query->bindValue(':id',$_SESSION['uniqueID'],PDO::PARAM_INT);
$query->execute();

// Gestion de l'image à afficher
if (!empty($id)) // Si le membre est connecté
{
	// Si le forum est vide alors on affiche que le forum est lu
	if ($data['forum_post'] == '' OR $data['forum_post'] == NULL OR $data['forum_post'] == 0){
		$ico_mess = 'message_lu.gif';
	}
	else
	{
		if ($data['tv_id'] == $id // S'il a lu le topic
		{
			if ($data['tv_post_id'] == $data['forum_last_post_id']) // S'il n'y a pas de nouveau message
			{
				$ico_mess = 'message_lu.gif';
			}
			else
			{
				$ico_mess = 'message_non_lu.gif'; // S'il y a un nouveau message
			}
		}
		else // S'il n'a pas lu le topic
		{
			$ico_mess = 'messagep_non_lu.gif';
		}
	}
} // S'il n'est pas connecté
else
{
	$ico_mess = 'forum_read.gif';
}

$query=$db->prepare('SELECT cat_id, cat_nom, 
forum_forum.forum_id, forum_name, forum_desc, forum_post, forum_topic, auth_view, forum_topic.topic_id,  forum_topic.topic_post, post_id, post_time, post_createur, membre_pseudo, 
membre_id 
FROM forum_categorie
LEFT JOIN forum_forum ON forum_categorie.cat_id = forum_forum.forum_cat_id
LEFT JOIN forum_post ON forum_post.post_id = forum_forum.forum_last_post_id
LEFT JOIN forum_topic ON forum_topic.topic_id = forum_post.topic_id
LEFT JOIN forum_membres ON forum_membres.membre_id = forum_post.post_createur
WHERE auth_view <= :lvl 
ORDER BY cat_ordre, forum_ordre DESC');
$query->bindValue(':lvl',$lvl,PDO::PARAM_INT);
$query->execute();
?>
<table>
<?php
//Début de la boucle
while($data = $query->fetch())
{
    //On affiche chaque catégorie
    if( $categorie != $data['cat_id'] )
    {
        //Si c'est une nouvelle catégorie on l'affiche
       
        $categorie = $data['cat_id'];
        ?>
        <tr>
        <th></th>
        <th class="titre"><strong><?php echo stripslashes(htmlspecialchars($data['cat_nom'])); ?>
        </strong></th>             
        <th class="nombremessages"><strong>Sujets</strong></th>       
        <th class="nombresujets"><strong>Messages</strong></th>       
        <th class="derniermessage"><strong>Dernier message</strong></th>   
        </tr>
        <?php
               
    }}
if (verif_auth($data['auth_view']))
{
//Affichage des forums
    // Ce super echo de la mort affiche tous
    // les forums en détail : description, nombre de réponses etc...

    echo'<tr><td><img src="./images/'.$ico_mess.'.gif" alt="message" /></td>
    <td class="titre"><strong>
    <a href="./voirforum.php?f='.$data['forum_id'].'">
    '.stripslashes(htmlspecialchars($data['forum_name'])).'</a></strong>
    <br />'.nl2br(stripslashes(htmlspecialchars($data['forum_desc']))).'</td>
    <td class="nombresujets">'.$data['forum_topic'].'</td>
    <td class="nombremessages">'.$data['forum_post'].'</td>';

    // Deux cas possibles :
    // Soit il y a un nouveau message, soit le forum est vide
    if (!empty($data['forum_post']))
    {
         //Selection dernier message
	 $nombreDeMessagesParPage = $config['post_par_page'];
         $nbr_post = $data['topic_post'] +1;
	 $page = ceil($nbr_post / $nombreDeMessagesParPage);
		 
         echo'<td class="derniermessage">
         '.date('H\hi \l\e d/M/Y',$data['post_time']).'<br />
         <a href="./voirprofil.php?m='.stripslashes(htmlspecialchars($data['membre_id'])).'&amp;action=consulter">'.$data['membre_pseudo'].'  </a>
         <a href="./voirtopic.php?t='.$data['topic_id'].'&amp;page='.$page.'#p_'.$data['post_id'].'">
         <img src="./images/go.gif" alt="go" /></a></td></tr>';

     }
     else
     {
         echo'<td class="nombremessages">Pas de message</td></tr>';
     }

     //Cette variable stock le nombre de messages, on la met à jour
     $totaldesmessages += $data['forum_post'];

     //On ferme notre boucle et nos balises
 //fin de la boucle
$query->CloseCursor();}
else
{
echo'<td class="nombremessages">Pas de message</td></tr>';
}
 //Fin de la vérification d'autorisation
 echo '</table></div>';
//Le pied de page ici :
echo'<div id="footer">
<h2>
Qui est en ligne ?
</h2>
';

//On compte les membres
$TotalDesMembres = $db->query('SELECT COUNT(*) FROM forum_membres')->fetchColumn();
$query->CloseCursor();	
$query = $db->query('SELECT membre_pseudo, membre_id FROM forum_membres ORDER BY membre_id DESC LIMIT 0, 1');
$data = $query->fetch();
$derniermembre = stripslashes(htmlspecialchars($data['membre_pseudo']));

echo'<p>Le total des messages du forum est <strong>'.$totaldesmessages.'</strong>.<br />';
echo'Le site et le forum comptent <strong>'.$TotalDesMembres.'</strong> membres.<br />';
echo'Le dernier membre est <a href="./voirprofil.php?m='.$data['membre_id'].'&amp;action=consulter">'.$derniermembre.'</a>.</p>';
$query->CloseCursor();?>
</div><div id="pied_de_page"><?php include("../pied_de_page.php");?></div> 
</body>
</html>

Et il y a une erreur :
Parse error: syntax error, unexpected 'if' (T_IF) in C:\wamp\www\tests\forum\index.php on line 73
Pourriez-vous m'aider ?
Hors ligne zemappeur # Posté le 31/01/2012 à 14:31:28
Onze Arold Again
Avatar

Avis : Très bon
Flux RSS

Ville : Marquay
Pays : France métropolitaine

Bonjour,

Pour la suite par rapport à l'index du forum je me disais simplement que si tu été pas le dernier à avoir poster un message c'est qu'il y a des nouveaux messages enregistrer. Es-ce bien comme ça qu'il faudrait coder le script ?

Sachant que l'on peux voir le dernier à avoir écris un message on peux simplifier le code !

Image utilisateur
Image utilisateur
Image utilisateur
 
Hors ligne billyd # Posté le 18/03/2012 à 21:19:21

Un grand merci à toi pour ce magnifique tuto !
Super bien fait, qui m'a permis de me mettre a jour sur php et PDO sans passer par le grand tuto de M@teo (qui m'a quand même formé) :lol: et de créer mon forum sans passer par phpBB ou autre car j'en avait marre de toujours utiliser des systèmes difficilement personnalisables et lourd...
Je tiens à remercier aussi "coolfarmer" car son message sur le système "Lu/non lu" ma beaucoup aider. :p Il est vrai que l'on peut avoir un peut de mal par rapport à la page d'index, si non, encore une fois merci pour ce tuto vraiment super ! ^^

A bientôt ! :D
Hors ligne Mika56 # Posté le 14/04/2012 à 15:11:25
Avatar

Ville : Caudan
Pays : France métropolitaine

Citation : mwsaz
Salut,

En SQL correct,
Code : SQL
1
2
INSERT INTO forum_whosonline VALUES(:id, :time,:ip)
ON DUPLICATE KEY UPDATE

devient
Code : SQL
1
REPLACE INTO forum_whosonline VALUES(:id, :time,:ip)


Salut,

Je confirme que cela fonctionne.
De plus, on peut étendre ceci au système de vues/non vues, plutôt que d'utiliser une condition pour savoir si on fait un INSERT ou un UPDATE.

Mika.

Voir tous les commentaires