TP : site et profils
Comme prévu, ce chapitre est aussi un TP ; cependant, il sera sensiblement plus long que le précédent, je vais donc le découper en deux parties. Une première portera sur la mise en place de statistiques (même si le terme est assez exagéré pour ce que nous allons faire), et de la page de visualisation des profils, tandis que la seconde partie portera sur l'édition de son profil ou de celui d'un membre (administration oblige).
Pour ce TP, vous n'aurez besoin que des connaissances acquises jusque-là, nous pouvons donc y aller sans plus tarder.
Bon, nous sommes d'accord : le mot statistiques est assez ambigu, on ne va pas faire des choses ultra-poussées comme le nombre de visiteurs uniques par mois, le nombre de pages lues, le nombre de Français qui parcourent votre site et j'en passe ; cela, on y réfléchira peut-être en partie II, mais pour le moment, on se cantonne à des choses très simples.
Ici, je veux donner une utilité à
colg.php, je vais donc vous montrer ce que j'y ai mis, et vous allez essayer de me créer les pages et fonctions nécessaires pour faire marcher tout ce bazar !
Code : PHP1
2
3
4
5 | <div id="statistiques"><h1>Site</h1>
<a href="<?php echo ROOTPATH; ?>/stats.php?see=nb_membres"><?php echo $num1 = get('nb_membres'); if($num1 <= 1) echo ' membre inscrit'; else echo ' membres inscrits'; ?></a><br/>
<a href="<?php echo ROOTPATH; ?>/stats.php?see=connectes"><?php echo $num2 = get('connectes'); if($num2 <= 1) echo ' visiteur'; else echo ' visiteurs' ?></a><br/>
<a href="<?php echo ROOTPATH; ?>/stats.php?see=passed">Dernières visites</a><br/>
</div>
|
Voilà, c'est pas bien gros, mais ça va vous occuper quelques temps.

Détaillons ce que nous voulons.
À la racine de votre site (ou espace de test), créez le fichier
stats.php.
Ce fichier recevra une variable
$_GET['see'] qui lui permettra de savoir quoi faire.
Les différents cas
nb_membres.php
Si la variable
$_GET['see'] vaut
nb_membres, alors
stats.php inclura
stats/nb_membres.php qui lui affichera une liste de tous les membres inscrits, avec leur pseudo et dates d'inscription (mis en page).
Nous essayerons d'améliorer cette liste en partie II.
connectes.php
Si la variable
$_GET['see'] vaut
connectes, alors
stats.php inclura la page
stats/connectes.php qui dépendra elle-même d'une variable
$_GET['a'].
La page
connectes.php devra afficher une liste des
membres inscrits connectés si
$_GET['a'] diffère de 1 ou 2.
Elle montrera une liste des
invités connectés si
$_GET['a'] vaut 2, enfin elle proposera une liste complète si
$_GET['a'] vaut 1.
Mais... Mais ?! Tu veux qu'on la sorte d'où, la liste des connectés ?!
Ah tiens, excellente question !
Il est temps de créer une deuxième table SQL !
Code : SQL1
2
3
4
5
6
7
8 | CREATE TABLE `connectes` (
`connectes_id` int(11) NOT NULL, --id du membre connecté, vaut -1 si le membre est un invité.
`connectes_ip` varchar(16) NOT NULL, --l'ip du connecté, fera appel à une fonction getIp().
`connectes_membre` varchar(16) NOT NULL, --est-ce que le connecté est un membre ? Vaut 1 si oui, vaut l'adresse IP du connecté sinon.
`connectes_actualisation` int(11) NOT NULL, --dernière actualisation
UNIQUE KEY `membre_id` (`connectes_id`,`connectes_membre`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
*/
|
Bien : maintenant, nous allons donc devoir faire des modifications à
actualiser_session()
!
Premièrement, à chaque fois que le membre actualise une page, sa session est vérifiée et validée à nouveau, il faut donc qu'à chaque fois que le membre actualise une page, on mette à jour le champ
membre_derniere_visite avec un code dans ce goût :
Code : PHP1
2
3
4 | <?php
mysql_query("UPDATE membres SET membre_derniere_visite = ".time()." WHERE membre_id = ".$_SESSION['membre_id']) or exit(mysql_error());
queries();
?>
|
Enfin, il va falloir mettre à jour la table des connectés à chaque actualisation de page ; mettez ce code juste avant de fermer la fonction :
Code : PHP1
2
3
4
5 | <?php
if(isset($_SESSION['membre_id'])) $id = $_SESSION['membre_id'];
else $id = -1;
updateConnectes($id);
?>
|
Vous avez donc une fonction supplémentaire à définir.
Alors là j'en vois venir certains : à quoi sert le champ
connectes_actualisation dans la table
connectes si l'on met à jour les deux à chaque fois ?
Eh bien la table des connectés est débarrassée des champs où l'actualisation dépasse les 300 secondes (5 minutes) : donc si on se base dessus, on ne peut pas savoir quand un membre est passé pour la dernière fois.
A contrario, si on se base sur le champ de la table
membres, comment sait-on quand un membre est connecté ou non, et comment recenser les invités ? Au final, nous ne gagnerions rien à ne pas utiliser deux champs au lieu d'un.
Enfin, la fonction
getIp()
est définie ainsi :
Code : PHP1
2
3
4
5
6
7 | <?php
function getIp()
{
if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])) return $_SERVER['HTTP_X_FORWARDED_FOR'];
else return $_SERVER['REMOTE_ADDR'];
}
?>
|
Elle permet de mieux identifier quelqu'un qui passerait par un
proxy transparent, par exemple, celui de son université ou autre.
Certains hébergeurs gratuits (olympe network, par exemple) utilisent un proxy intermédiaire pour sécuriser leur infrastructure, si bien que pour avoir les IP des membres, j'ai été obligé de mettre cette fonction en place.
Cette fonction ne peut en aucun cas retourner l'IP d'un membre qui passerait par un proxy visant à le rendre anonyme ; un proxy, je vous le rappelle, permet de passer par un ordinateur avant d'envoyer une requête à votre serveur.
Si certains ne sont même pas conscients de passer par un proxy (exemple d'une université, d'une bibilothèque), d'autres le font pour pouvoir avoir accès à des données réservées à des habitants d'un pays précis ou pour pirater en toute tranquillité (ou presque... :o)). Sans lancer un débat sur le bien-fondé des proxies, il peut être utile d'utiliser cette fonction.
Bref, pour obtenir l'IP de quelqu'un, il ne vous reste plus qu'à faire :
Code : PHP
Pratique.
Bien, nous en avons, je pense, fini avec
connectes.php.
passed.php
Si la variable
$_GET['see'] vaut
passed, alors
stats.php inclura la page
stats/passed.php.
Cette page, au premier abord similaire à
connectes.php, est
directement tirée du SdZ (un peu comme toutes les mises en page que je vous propose, l'objectif étant d'avoir un joli rendu).

Elle affichera une liste exhaustive des membres avec leur pseudo, leur date de dernière connexion, ainsi que leur statut actuel (connecté ou non).
Elle ne changera donc pas dans la partie II.
Autre cas : index.php
Si la variable $_GET['see'] a une autre valeur, alors
stats.php inclura la page
stats/index.php.
Cet index des stats contiendra une liste des pages de statistiques accessibles (3), ainsi que d'autres pages de statistiques que vous auriez pu mettre en place vous-mêmes.
Qu'on soit bien clairs : cette page n'est pas indispensable, vous pouvez mettre une redirection si vous le préférez.
Les pages nb_membres.php, connectes.php, passed.php et index.php sont toutes les quatre dans un dossier stats à la racine de votre site (ou dossier de tests), sinon ma correction diffèrera de votre système !
Bien, bien, maintenant que nous avons planté le décor, je pense qu'il est temps pour vous d'entrer en scène : pendant ce temps, je vais aller mettre mon costume de prof.
Bonne chance !
Alors, ça bosse dur ?
Voilà sans plus attendre une correction détaillée de l'exercice.
colg.php (je la remets au cas où)
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 | <?php
/*
Neoterranos & LkY
Page colg.php
La colonne de gauche de votre site (page incluse).
Quelques indications (utiliser l'outil de recherche et rechercher les mentions données) :
Liste des fonctions :
--------------------------
Aucune fonction
--------------------------
Liste des informations / erreurs :
--------------------------
Aucune information / erreur
--------------------------
*/
?>
<div id="statistiques"><h1>Site</h1>
<a href="<?php echo ROOTPATH; ?>/stats.php?see=nb_membres"><?php echo $num1 = get('nb_membres'); if($num1 <= 1) echo ' membre inscrit'; else echo ' membres inscrits'; ?></a><br/>
<a href="<?php echo ROOTPATH; ?>/stats.php?see=connectes"><?php echo $num2 = get('connectes'); if($num2 <= 1) echo ' visiteur'; else echo ' visiteurs' ?></a><br/>
<a href="<?php echo ROOTPATH; ?>/stats.php?see=passed">Dernières visites</a><br/>
</div>
|
On définit donc
get()
.
Code : PHP 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | <?php
function get($type) //je ne me suis pas foulé. :D
{
if($type == 'nb_membres')
{
$count = sqlquery("SELECT COUNT(*) AS nbr FROM membres", 1);
return $count['nbr'];
}
else if($type == 'connectes')
{
$count = sqlquery("SELECT COUNT(*) AS nbr FROM connectes", 1);
return $count['nbr'];
}
else
{
return 0;
}
}
?>
|
On définit aussi une fonction de mise en page de la date (inspirée de la gestion des dates du SdZ) :
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 | <?php
function mepd($date)
{
if(intval($date) == 0) return $date;
$tampon = time();
$diff = $tampon - $date;
$dateDay = date('d', $date);
$tamponDay = date('d', $tampon);
$diffDay = $tamponDay - $dateDay;
if($diff < 60 && $diffDay == °)
{
return 'Il y a '.$diff.'s';
}
else if($diff < 600 && $diffDay == 0)
{
return 'Il y a '.floor($diff/60).'m et '.floor($diff%60).'s';
}
else if($diff < 3600 && $diffDay == 0)
{
return 'Il y a '.floor($diff/60).'m';
}
else if($diff < 7200 && $diffDay == 0)
{
return 'Il y a '.floor($diff/3600).'h et '.floor(($diff%3600)/60).'m';
}
else if($diff < 24*3600 && $diffDay == 0)
{
return 'Aujourd\'hui à '.date('H\hi', $date);
}
else if($diff < 48*3600 && $diffDay == 1)
{
return 'Hier à '.date('H\hi', $date);
}
else
{
return 'Le '.date('d/m/Y', $date).' à '.date('h\hi', $date).'.';
}
}
?>
|
Vous remarquerez que j'ai vraiment un problème avec les
switch, je ne les aime vraiment pas.
C'est notre point de départ, à partir d'ici, vous avez normalement créé
stats.php :
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 | <?php
/*
Neoterranos & LkY
Page stats.php
Statistiques du site.
Quelques indications (utiliser l'outil de recherche et rechercher les mentions données) :
Liste des fonctions :
--------------------------
Aucune fonction
--------------------------
Liste des informations / erreurs :
--------------------------
$_GET['see'] contient des caractères invalides (tentative de hack ?)
--------------------------
*/
session_start();
header('Content-type: text/html; charset=utf-8');
include('includes/config.php');
/********Actualisation de la session...**********/
include('includes/fonctions.php');
connexionbdd();
actualiser_session();
/********Fin actualisation de session...**********/
if($_GET['see'] == '' || !isset($_GET['see']))
{
include('stats/index.php');
}
else
{
if(strpos($_GET['see'], '.') !== FALSE || strpos($_GET['see'], ':') !== FALSE || strpos($_GET['see'], 'http') !== FALSE) //$_GET['see'] contient des caractères invalides (tentative de hack ?)
{
include('stats/index.php');
}
else if(file_exists('stats/'.$_GET['see'].'.php'))
{
include('stats/'.$_GET['see'].'.php');
}
else
{
include('stats/index.php');
}
}
include('includes/bas.php');
mysql_close();
?>
|
Voilà, j'ai procédé ainsi pour inclure autant de fichiers que voulu, cette méthode est sécurisée.
Il n'y a, a priori, rien que vous ne puissiez comprendre.
Passons à stats/nb_connectes.php
Comme vous l'avez vu, nous n'avons absolument pas donné de nom à notre page, le nom sera défini dans la page incluse :
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
/*
Neoterranos & LkY
Page nb_membres.php
Affiche une liste complète des membres.
Quelques indications (utiliser l'outil de recherche et rechercher les mentions données) :
Liste des fonctions :
--------------------------
Aucune fonction
--------------------------
Liste des informations / erreurs :
--------------------------
Aucune information / erreur
--------------------------
*/
/********En-tête et titre de page*********/
$titre = 'Liste des membres du site';
include('includes/haut.php'); //contient le doctype, et head.
/**********Fin en-tête et titre***********/
?>
<div id="colonne_gauche">
<?php
include('includes/colg.php');
?>
</div>
<div id="contenu">
<div id="map">
<a href="index.php">Accueil</a> => <a href="stats.php?see=nb_membres">Liste des membres</a>
</div>
|
Jusqu'ici, rien de bien nouveau.
Maintenant, nous allons, via une requête, récupérer tous les membres, les classer par ID (SQL le fait très bien), et les afficher dans un tableau, je pense d'ailleurs qu'il peut être utile de revoir le
chapitre de M@teo sur les tableaux (cours XHTML/CSS) :
Code : PHP 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 | <?php
$membre_query = sqlquery("SELECT membre_id, membre_pseudo, membre_inscription
FROM membres
ORDER BY membre_id ASC", 2); //ORDER BY s'occupe du tri !
$i = 0;
?>
<div class="membre_liste">
<table>
<thead>
<th>N° du membre</th>
<th>Pseudonyme</th>
<th>Date d'inscription</th>
</thead>
<tfoot>
<th>N° du membre</th>
<th>Pseudonyme</th>
<th>Date d'inscription</th>
</tfoot>
|
Ici, on a préparé la tête et le pied du tableau, n'oubliez pas qu'on les met avant la balise
<tbody>
!
Mais tu ne fais pas de limit dans ta requête SQL ?
Non, pour le moment, on n'en aura pas besoin, mais effectivement, quand on a 113 326 membres inscrits sur son site, et une requête à rallonge avec des jointures pour savoir si le membre est dans tel ou tel groupe (notez que le SdZ semble avoir une façon plus simple de faire : max un groupe pour un membre, donc peut-être pas de requête à rallonge), cela peut devenir utile.

Cependant, on aura besoin de définir une fonction page dans ce cas-là, qui gèrera la position de la page visualisée par rapport à la première et à la dernière page, donc on verra cela plus tard, ce n'est pas indispensable tout de suite.
Affichons maintenant les membres :
Code : PHP 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 | <tbody>
<?php
while(isset($membre_query[$i]))
{
echo '<tr class="ligne_'.($i%2).'">
<td>'.$membre_query[$i]['membre_id'].'</td>
<td><a href="membres/user.php?id='.$membre_query[$i]['membre_id'].'">'.htmlspecialchars($membre_query[$i]['membre_pseudo'], ENT_QUOTES).'</a></td>
<td>'.mepd($membre_query[$i]['membre_inscription']).'</td>
</tr>
';
$i++;
}
if($i == 0) echo '<tr><td colspan="3">Pas de membre trouvé.</td></tr>';
?>
</tbody>
</table>
</div>
</div>
|
Et un peu de CSS :
Code : CSS 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 | table {
margin: auto;
margin-top: 10px;
border: 1px solid black;
text-align: center;
border-collapse: collapse;
}
th {
border: 1px solid black;
text-align: center;
}
td {
border: 1px solid black;
text-align: center;
}
.ligne_0 {
background-color: #dfe5f5;
}
.ligne_1 {
background-color: #edf1f8;
}
|
Voilà ! Votre page
nb_membres est finie !
Vous pouvez l'admirer avec joie !
Passons à l'affichage des connectés, et donc la création de fonctions supplémentaires.
actualiser_session()
:
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 | <?php
function actualiser_session()
{
if(isset($_SESSION['membre_id']) && intval($_SESSION['membre_id']) != 0) //Vérification id
{
//utilisation de la fonction sqlquery, on sait qu'on aura qu'un résultat car l'id d'un membre est unique.
$retour = sqlquery("SELECT membre_id, membre_pseudo, membre_mdp FROM membres WHERE membre_id = ".intval($_SESSION['membre_id']), 1);
//Si la requête a un résultat (id est : si l'id existe dans la table membres)
if(isset($retour['membre_pseudo']) && $retour['membre_pseudo'] != '')
{
if($_SESSION['membre_mdp'] != $retour['membre_mdp'])
{
//Dehors vilain pas beau !
$informations = Array(/*Mot de passe de session incorrect*/
true,
'Session invalide',
'Le mot de passe de votre session est incorrect, vous devez vous reconnecter.',
'',
'membres/connexion.php',
3
);
require_once('../information.php');
vider_cookie();
session_destroy();
exit();
}
else
{
//Validation de la session.
$_SESSION['membre_id'] = $retour['membre_id'];
$_SESSION['membre_pseudo'] = $retour['membre_pseudo'];
$_SESSION['membre_mdp'] = $retour['membre_mdp'];
mysql_query("UPDATE membres SET membre_derniere_visite = ".time()." WHERE membre_id = ".$_SESSION['membre_id']) or exit(mysql_error());
queries();
}
}
}
else //On vérifie les cookies et sinon pas de session
{
if(isset($_COOKIE['membre_id']) && isset($_COOKIE['membre_mdp'])) //S'il en manque un, pas de session.
{
if(intval($_COOKIE['membre_id']) != 0)
{
//idem qu'avec les $_SESSION
$retour = sqlquery("SELECT membre_id, membre_pseudo, membre_mdp FROM membres WHERE membre_id = ".intval($_COOKIE['membre_id']), 1);
if(isset($retour['membre_pseudo']) && $retour['membre_pseudo'] != '')
{
if($_COOKIE['membre_mdp'] != $retour['membre_mdp'])
{
//Dehors vilain tout moche !
$informations = Array(/*Mot de passe de cookie incorrect*/
true,
'Mot de passe cookie erroné',
'Le mot de passe conservé sur votre cookie est incorrect, vous devez vous reconnecter.',
'',
'membres/connexion.php',
3
);
require_once('../information.php');
vider_cookie();
session_destroy();
exit();
}
else
{
//Bienvenue :D
$_SESSION['membre_id'] = $retour['membre_id'];
$_SESSION['membre_pseudo'] = $retour['membre_pseudo'];
$_SESSION['membre_mdp'] = $retour['membre_mdp'];
mysql_query("UPDATE membres SET membre_derniere_visite = ".time()." WHERE membre_id = ".$_SESSION['membre_id']) or exit(mysql_error());
queries();
}
}
}
else //cookie invalide, erreur plus suppression des cookies.
{
$informations = Array(/*L'id de cookie est incorrect*/
true,
'Cookie invalide',
'Le cookie conservant votre id est corrompu, il va donc être détruit, vous devez vous reconnecter.',
'',
'membres/connexion.php',
3
);
require_once('../information.php');
vider_cookie();
session_destroy();
exit();
}
}
else
{
//Fonction de suppression de toutes les variables de cookie.
if(isset($_SESSION['membre_id'])) unset($_SESSION['membre_id']);
vider_cookie();
}
}
if(isset($_SESSION['membre_id'])) $id = $_SESSION['membre_id'];
else $id = -1;
updateConnectes($id);
}
?>
|
updateConnectes()
et
getIp()
:
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 | <?php
function updateConnectes($id)
{
$ip = getIp();
if($id != -1)
{
$id = $_SESSION['membre_id'];
$additionnal = 1; //la variable à mettre dans connectes_membre
}
else
{
$additionnal = $ip;
}
mysql_query("DELETE FROM connectes WHERE connectes_actualisation < ".(time()-300)) or exit(mysql_error()); //MàJ générale des connectés
mysql_query("INSERT INTO connectes VALUES(".$id.", '".$ip."', '".$additionnal."', ".time().")
ON DUPLICATE KEY UPDATE connectes_actualisation=".time().", connectes_ip='".$ip."'") or exit(mysql_error()); //tiens, tiens, ON DUPLICATE... :o
queries(2);
}
function getIp()
{
if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])) return $_SERVER['HTTP_X_FORWARDED_FOR'];
else return $_SERVER['REMOTE_ADDR'];
}
?>
|
Quelques explications s'imposent.

Je vous ai fait utiliser un champ
connectes_membre, dans lequel on insère ici
$additionnal : à quoi ce champ sert-il ?
Si vous avez bien regardé la structure de la table des connectés, vous avez dû remarquer ceci :
Code : SQL1 | UNIQUE KEY `membre_id` (`connectes_id`,`connectes_membre`)
|
Cette ligne place une condition d'unicité sur deux champs en même temps :
connectes_id et
connectes_membre.
Une autre façon de voir la ligne SQL que j'ai citée, c'est de l'interpréter en français : "Si, au moment d'une insertion, la valeur de
connectes_id et la valeur de
connectes_membre sont déjà
toutes les deux prises sur une même ligne, retourner une erreur.".
L'intérêt est en effet de permettre à plusieurs visiteurs d'être présents en même temps, donc de comptabiliser chaque IP comme un visiteur, tout en ne permettant à un membre inscrit de n'être comptabilisé qu'une fois, donc que son
IP ne soit pas une condition d'unicité, mais cette fois son
id et
son statut de membre !
Donc si le membre ayant
l'id 1 est connecté, le champ
connectes_id vaut 1, et le champ
connectes_membre vaut 1 aussi, s'il actualise, on lui refuse l'insertion d'une nouvelle ligne, car elle transgresse la condition d'unicité ; par contre, pour les invités, le champ
connectes_membre valant leur IP, on peut avoir sans problèmes plusieurs invités connectés en même temps pour un peu qu'ils aient des IP différents.

Cependant, un problème se pose si un membre ou un invité déjà enregistré dans la table
connectes actualise une page, l'insertion étant refusée, il faut donc faire un
UPDATE.
C'est ici que
ON DUPLICATE KEY UPDATE intervient.
Plutôt que de faire une nouvelle requête pour mettre à jour la connexion, on appose cette condition en fin de requête d'insertion et les champs à mettre à jour.
Cela revient à dire en français : "Si l'insertion transgresse la condition d'unicité, mettre à jour le champ
connectes_actualisation à la valeur
time()
."
Ainsi, on condense deux requêtes en une.
C'est vrai qu'à première vue, ce n'est pas évident ; j'ai essayé de vous expliquer cela le plus simplement possible, mais je sais déjà que mes explications ne conviendront pas à certains, sur la condition d'unicité je ne peux rien faire de plus. Par contre, pour
ON DUPLICATE KEY UPDATE, vous pouvez vous rendre
ici (attention, page en anglais).
On peut enfin attaquer connectes.php
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 | <?php
/*
Neoterranos & LkY
Page connectes.php
Affiche une liste complète des membres connectes.
Quelques indications (utiliser l'outil de recherche et rechercher les mentions données) :
Liste des fonctions :
--------------------------
Aucune fonction
--------------------------
Liste des informations / erreurs :
--------------------------
Aucune information / erreur
--------------------------
*/
/********En-tête et titre de page*********/
$titre = 'Liste des connectés';
include('includes/haut.php'); //contient le doctype, et head.
/**********Fin en-tête et titre***********/
?>
<div id="colonne_gauche">
<?php
include('includes/colg.php');
?>
</div>
<div id="contenu">
<div id="map">
<a href="index.php">Accueil</a> => <a href="stats.php?see=connectes&a=<?php echo intval($_GET['a']); ?>">Liste des connectés</a>
</div>
<h1>Liste des connectés</h1>
|
Ensuite, vient le moment de s'occuper du menu, et donc de la requête SQL à effectuer en fonction des liens sélectionnés.
Moi je ne m'embête pas, je fais une condition
if/else if, un
switch est aussi possible.
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
if($_GET['a'] == 1)
{
$id = '';
}
else if($_GET['a'] == 2)
{
$id = ' AND connectes_id = -1';
}
else
{
$id = ' AND connectes_id <> -1';
}
$membre_query = sqlquery("SELECT membre_id, membre_pseudo, connectes_actualisation
FROM connectes
LEFT JOIN membres ON membre_id = connectes_id
WHERE connectes_actualisation > ".(time()-300).$id."
ORDER BY connectes_actualisation DESC", 2);
?>
|
C'est un peu du bidouillage, mais je préfère cela plutôt que de monter trois requêtes différentes.

Passons au mini-menu : comme on veut qu'il soit centré, on va le prendre dans un
div avec la propriété CSS qui convient :
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 | <!--menu//-->
<div class="center">
<?php
if($_GET['a'] == 1 || $_GET['a'] == 2)
{
echo '<a href="stats.php?see=connectes">Voir seulement les membres connectés</a>';
$avt = 1;
}
if($_GET['a'] != 2)
{
if($avt == 1) echo ' - ';
echo '<a href="stats.php?see=connectes&a=2">Voir seulement les invités connectés</a>';
$avt = 1;
}
if($_GET['a'] != 1)
{
if($avt == 1) echo ' - ';
echo '<a href="stats.php?see=connectes&a=1">Voir les membres et les invités connectés</a>';
}
?>
</div>
|
Ici aussi, nous n'affichons que les menus proposant une page différente de celle que l'on visualise actuellement, donc on s'arrange pour rendre cela joli, même s'il faut du coup "bidouiller" un peu (je n'aime pas le mot bidouiller dans ce cas-là, car ce n'est pas vraiment du bidouillage, quelle que soit la méthode employée, le principe est le même, sauf si l'on affiche les trois menus, là au moins on ne s'ennuie pas, même pas besoin de PHP).
Il ne reste plus qu'à mettre le tableau en place, avec des liens pointant sur les membres, mais pas sur les invités :
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 | <!--tableau//-->
<table>
<thead>
<th>N° du membre</th>
<th>Pseudonyme</th>
<th>Dernière connexion</th>
</thead>
<tfoot>
<th>N° du membre</th>
<th>Pseudonyme</th>
<th>Dernière connexion</th>
</tfoot>
<tbody>
<?php
$i = 0;
while(isset($membre_query[$i]))
{
if($membre_query[$i]['membre_id'] != '')
{
$lien = '<a href="membres/user.php?id='.$membre_query[$i]['membre_id'].'">';
$lien2 = '</a>';
}
else
{
$lien = '';
$lien2 = '';
}
if($membre_query[$i]['membre_id'] == '') //un invité n'a pas de lien, ni d'id.
{
$membre_query[$i]['membre_id'] = 'Non renseigné'; //
$membre_query[$i]['membre_pseudo'] = 'Invité';
}
echo '<tr class="ligne_'.($i%2).'">
<td>'.$membre_query[$i]['membre_id'].'</td>
<td>'.$lien.htmlspecialchars($membre_query[$i]['membre_pseudo'], ENT_QUOTES).$lien2.'</td>
<td>'.mepd($membre_query[$i]['connectes_actualisation']).'</td>
</tr>
';
$i++;
}
if($i == 0) echo '<tr><td colspan="3">Pas de membre trouvé.</td></tr>';
?>
</tbody>
</table>
</div>
|
Voilà pour
connectes.php.
passed.php
Allez, on attaque
passed.php, elle se passe d'explications, elle est très similaire aux précédentes.
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 | <?php
/*
Neoterranos & LkY
Page passed.php
Affiche une liste complète des dates de visite des membres.
Quelques indications (utiliser l'outil de recherche et rechercher les mentions données) :
Liste des fonctions :
--------------------------
Aucune fonction
--------------------------
Liste des informations / erreurs :
--------------------------
Aucune information / erreur
--------------------------
*/
/********En-tête et titre de page*********/
$titre = 'Liste des dernières visites';
include('includes/haut.php'); //contient le doctype, et head.
/**********Fin en-tête et titre***********/
?>
<div id="colonne_gauche">
<?php
include('includes/colg.php');
?>
</div>
<div id="contenu">
<div id="map">
<a href="index.php">Accueil</a> => <a href="stats.php?see=passed">Liste des visites</a>
</div>
<h1>Liste des visites</h1>
<?php
$membre_query = sqlquery("SELECT membre_id, membre_pseudo, membre_derniere_visite, connectes_id
FROM membres
LEFT JOIN connectes
ON membre_id = connectes_id
ORDER BY membre_derniere_visite DESC", 2);
$i = 0;
?>
<div class="membre_liste">
<table>
<thead>
<th>N° du membre</th>
<th>Pseudonyme</th>
<th>Dernière connexion</th>
<th>Statut</th>
</thead>
<tfoot>
<th>N° du membre</th>
<th>Pseudonyme</th>
<th>Dernière connexion</th>
<th>Statut</th>
</tfoot>
<tbody>
<?php
while(isset($membre_query[$i]))
{
if($membre_query[$i]['connectes_id'] == $membre_query[$i]['membre_id']) //gestion des statuts de connexion
{
$statut = '<span class="actif">Connecté</span>';
}
else
{
$statut = '<span class="inactif">Déconnecté</span>';
}
echo '<tr class="ligne_'.($i%2).'">
<td>'.$membre_query[$i]['membre_id'].'</td>
<td><a href="membres/user.php?id='.$membre_query[$i]['membre_id'].'">'.htmlspecialchars($membre_query[$i]['membre_pseudo'], ENT_QUOTES).'</a></td>
<td>'.mepd($membre_query[$i]['membre_derniere_visite']).'</td>
<td>'.$statut.'</td>
</tr>
';
$i++;
}
if($i == 0) echo '<tr><td colspan="4">Pas de membre trouvé.</td></tr>';
?>
</tbody>
</table>
</div>
</div>
|
Ici, on ne gère pas les invités.
Il ne reste plus qu'à mettre l'index des stats :
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 | <?php
/*
Neoterranos & LkY
Page index.php
Index des statistiques du site (page incluse).
Quelques indications (utiliser l'outil de recherche et rechercher les mentions données) :
Liste des fonctions :
--------------------------
Aucune fonction
--------------------------
Liste des informations / erreurs :
--------------------------
Aucune information / erreur
--------------------------
*/
/********En-tête et titre de page*********/
$titre = 'Statistiques du site';
include('includes/haut.php'); //contient le doctype, et head.
/**********Fin en-tête et titre***********/
?>
<div id="colonne_gauche">
<?php
include('includes/colg.php');
?>
</div>
<div id="contenu">
<div id="map">
<a href="index.php">Accueil</a> => <a href="stats.php">Statistiques</a>
</div>
<h1>Statistiques</h1>
Bienvenue sur la page des statistiques du site.<br/>
Ici, vous pourrez voir les statistiques concernant les membres, les forums, les news, etc., etc. :)<br/>
Bonne visite !
<h2>Membres</h2>
<div class="center">
-> <a href="stats.php?see=nb_membres">Il y a <?php echo $num1; if($num1 <= 1) echo ' membre inscrit'; else echo ' membres inscrits'; ?>.</a><br/>
-> <a href="stats.php?see=connectes">Il y a <?php echo $num2; if($num2 <= 1) echo ' visiteur'; else echo ' visiteurs' ?>.</a><br/>
-> <a href="stats.php?see=passed">Voir les dernières visites de chaque membre.</a><br/>
</div>
</div>
|
Notez juste que je réutilise les variables définies dans
colg.php ; si vous supprimez le bloc sur les stats dans cette page, alors vous devrez les définir ici.
On définit enfin trois nouvelles propriétés CSS :
Code : CSS 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | .actif {
color: blue;
font-weight: blod;
}
.inactif {
color: red;
font-weight: bold;
}
h2 {
text-align:center;
text-decoration: underline;
color: #507090;
font-family:"trebuchet ms", verdana, sans-serif;
letter-spacing:1.1px;
font-variant:small-caps;
font-weight:bold;
font-size:19px;
margin-top:0;
}
|
Voilà, j'espère que vous avez tout compris.

Passons à l'exercice II !
Bien, les statistiques sont finies, et vous avez vu que l'on y a mis un lien vers une page
user.php (qui se trouvera dans le dossier
membres).
Il s'agit donc pour vous de la créer.

Le Site du Zér0 a une façon d'afficher les profils que je trouve particulièrement réussie, je vous suggère d'essayer de faire la même.
Il y a donc plusieurs choses que je veux y voir :
- le titre de la page doit contenir le pseudo du membre ;
- le statut de connexion du membre doit être visible ;
- sa date de naissance doit être visible ;
- son âge (calculé avec la date de naissance) doit être visible ;
- l'e-mail, le MSN, le yahoo ou toute autre messagerie doit être affichée par image.
Précisons le dernier point
Comme vous le savez, les adresses e-mail des membres sont a priori des données privées ; pour le moment, dans le cadre de notre système simple, on ne propose rien au membre pour le cacher, donc les robots spammeurs n'ont qu'à venir, lire les mails, et spammer les membres.
Le fait de les afficher par image est censé (je dis bien
censé) leur compliquer la tâche.
Ici,
ce n'est pas le cas, car je vais vous demander de créer un fichier
image.php qui affiche bêtement le texte qu'on lui file en get, donc forcément, le mail sera dans le code source, donc lisible par un bot.
L'objectif ici est juste de vous sensibiliser, on verra comment régler ce problème efficacement dans le TP suivant, en créant ces images et en les enregistrant dans un dossier spécifique lors de la modification du profil d'un membre ou de son inscription.
Une idée qui pourrait vous venir à l'esprit est de créer image.php et de la faire marcher avec deux GET ; un premier prendrait le pseudo, le deuxième le type de mail (email, msn, yahoo, gmail ou autre...), le souci est que cela imposerait une requête par image, lourd pour afficher un simple profil.
On modifiera donc dans le prochain TP la page user.php, la page image.php, la page trait-inscription.php.
Pour le moment on s'en fiche pas mal.

Pour le reste, il s'agit d'un bête affichage de données provenant de la BDD, vous savez faire ça depuis maintenant quelques temps.
Bonne chance !
Alors, c'est fini ?
On peut donc corriger votre travail.

On suivra la page en respectant les points que je vous avais donnés.
Tout d'abord, le pseudo doit figurer dans le titre de la page
user.php, cela implique de faire
sqlquery()
avant d'inclure
haut.php et de définir le titre.
D'abord, lançons notre page :
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 | <?php
/*
Neoterranos & LkY
Page index.php
Affichage de profil.
Quelques indications (utiliser l'outil de recherche et rechercher les mentions données) :
Liste des fonctions :
--------------------------
Aucune fonction
--------------------------
Liste des informations / erreurs :
--------------------------
Le membre n'existe pas
--------------------------
*/
session_start();
header('Content-type: text/html; charset=utf-8');
include('../includes/config.php');
/********Actualisation de la session...**********/
include('../includes/fonctions.php');
connexionbdd();
actualiser_session();
/********Fin actualisation de session...**********/
|
Maintenant, passons à la gestion avant affichage :
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 | <?php
/********Gestion avant affichage...***********/
if($_GET['id'] == '') //s'il n'y a pas d'id, on affiche la page du membre connecté...
{
if(isset($_SESSION['membre_id'])) $id = $_SESSION['membre_id'];
else $id = -1;
}
else $id = $_GET['id'];
$profil = sqlquery("SELECT * FROM membres
LEFT JOIN connectes
ON connectes_id = membre_id
WHERE membre_id=".intval($id), 1);
if($profil['membre_id'] == '' || $id == -1)
{
$informations = Array(/*L'id de cookie est incorrect*/
true,
'Page membre inconnue',
'Ce membre n\'existe pas.',
'',
'../index.php',
3
);
require_once('../information.php');
exit();
}
/********Fin gestion avant affichage************/
?>
|
Voilà, ce n'était pas plus dur que cela ; maintenant, on peut afficher
haut.php, le titre, etc.
Code : PHP 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | <?php
/********En-tête et titre de page*********/
$titre = 'Membre : '.htmlspecialchars($profil['membre_pseudo'], ENT_QUOTES).'';
include('../includes/haut.php'); //contient le doctype, et head.
/**********Fin en-tête et titre***********/
?>
<div id="colonne_gauche">
<?php
include('../includes/colg.php');
?>
</div>
|
La partie assez habituelle de toute page de notre site est prête, passons au contenu.
Code : PHP 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 | <!--contenu//-->
<div id="contenu">
<div id="map">
<a href="../index.php">Accueil</a> => <a href="user.php?id=<?php echo intval($profil['membre_id']); ?>">Profil de <?php echo htmlspecialchars($profil['membre_pseudo'], ENT_QUOTES); ?></a>
</div>
<h1>Profil de <?php echo htmlspecialchars($profil['membre_pseudo'], ENT_QUOTES); ?></h1>
<div class="profil_cellule_float">
<h2>Informations générales</h2>
<div class="avatar">
<?php
if($profil['membre_avatar'] == '')
{
echo 'Pas d\'avatar';
}
?>
</div>
|
Le sitemap porte aussi le nom du bonhomme, de même que le titre de la page.

Quant à l'avatar, pour le moment, à moins que vous n'ayez votre propre gestion des uploads, c'est pas vraiment le point fort de notre page.

Ensuite, on fait une liste des informations principales sur le membre ; je dis bien
sur le membre, pas sur sa personne, donc son pseudo, sa date d'inscription, son dernier passage sur le site, le groupe dans lequel il est (pour le moment aucun, a priori, on se basera donc sur
membre_banni), et s'il est connecté actuellement...
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 | <!--liste//-->
<ul>
<li><b>Pseudo :</b> <?php echo htmlspecialchars($profil['membre_pseudo'], ENT_QUOTES); ?></li>
<li><b>Date d'inscription :</b> <?php echo mepd($profil['membre_inscription']); ?></li>
<li><b>Groupe :</b> <?php if($profil['banni'] == 1) echo 'bannis'; else echo 'membres'; ?></li>
<li><b>Dernier passage :</b> <?php echo mepd($profil['membre_derniere_visite']); ?></li>
<li><b>Statut :</b>
<?php
if($profil['connectes_id'] == $profil['membre_id'])
{
?>
<span class="actif"><?php echo htmlspecialchars($profil['membre_pseudo'], ENT_QUOTES); ?> est connecté</span>
<?php
}
else
{
?>
<span class="inactif"><?php echo htmlspecialchars($profil['membre_pseudo'], ENT_QUOTES); ?> est déconnecté</span></li>
<?php
}
?>
</ul>
</div>
|
Comme vous le voyez, le point numéro 2 est respecté.

Tout de suite après, on ajoute des informations, sur la personne du membre cette fois, donc la date de naissance, l'âge, la ville, la profession, mais pas l'e-mail, c'est un peu à part.
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 | <!--infos complémentaires//-->
<div class="profil_cellule">
<h2>Informations complémentaires</h2>
<ul>
<li><b>Date de naissance :</b> <?php echo $profil['membre_naissance']; ?></li>
<li><b>Âge :</b> <?php echo age($profil['membre_naissance']); ?>
<?php
if(trim($profil['membre_profession']) != '') /*affichage de la profession*/
{
?>
<li><b>Profession :</b> <?php echo htmlspecialchars($profil['membre_profession'], ENT_QUOTES); ?></li>
<?php
}
if(trim($profil['membre_localisation']) != '') /*affichage de la ville*/
{
?>
<li><b>Ville :</b> <?php echo htmlspecialchars($profil['membre_localisation'], ENT_QUOTES); ?></li>
<?php
}
?>
</ul>
</div>
|
Voilà : on a bien la date de naissance et l'âge du membre.

D'ailleurs, occupons-nous de la fonction
age, il s'agit d'un calcul simple :
Code : PHP 1
2
3
4
5
6
7
8
9
10
11 | <?php
function age($birth)
{
$DATE = intArray(explode('/', $birth));
$try = mktime(0, 0, 0, $DATE[1], $DATE[0], date('Y'));
if(time() >= $try) $age = date('Y') - $DATE[2];
else $age = date('Y') - $DATE[2] - 1;
return $age;
}
?>
|
Tiens donc, voilà une nouvelle fonction :
intArray()
!
Ce n'est pas une fonction native, elle est juste là pour sécuriser un peu plus la date de naissance :
Code : PHP 1
2
3
4
5
6
7
8
9
10
11 | <?php
function intArray($Array)
{
foreach($Array as $cle => $element)
{
$Array[$cle] = intval($element);
}
return $Array;
}
?>
|
Passons maintenant à son activité sur le site (quand je vous dis que je me suis vraiment inspiré du SdZ, même si je fais ça moins bien...), cette case sera vide, nous n'avons pas de forum, de système de news, ou même de tutoriels.
Code : HTML1
2
3
4
5 | <!--activité//-->
<div class="profil_cellule_float">
<h2><?php echo htmlspecialchars($profil['membre_pseudo'], ENT_QUOTES); ?> et le site</h2>
Si vous avez un forum, ou des news, ou autre chose comme le Site du Zér0, c'est ici qu'il faudra mettre tout ça !
</div>
|
Enfin, passons aux moyens de contacter le membre :
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 | <!--contact//-->
<div class="profil_cellule">
<h2>Comment le joindre</h2>
<!--
L'adresse e-mail est généralement une information très privée, pour le moment
nous ne la protégeons pas, mais très vite nous le ferons.
//-->
S'il y a un module de MP sur votre site, ou si vous comptez en mettre un, mettez un lien. :)
<h3>Messageries</h3>
<ul>
<li><b>E-Mail :</b> <img src="image.php?tex=<?php echo htmlspecialchars($profil['membre_mail'], ENT_QUOTES); ?>"/></li>
<?php
if(trim($profil['membre_msn']) != '')
{
?>
<li><b>MSN :</b> <img src="image.php?tex=<?php echo htmlspecialchars($profil['membre_msn'], ENT_QUOTES); ?>"/></li>
<?php
}
if(trim($profil['membre_yahoo']) != '')
{
?>
<li><b>Yahoo :</b> <img src="image.php?tex=<?php echo htmlspecialchars($profil['membre_yahoo'], ENT_QUOTES); ?>"/></li>
<?php
}
if(trim($profil['membre_aim']) != '')
{
?>
<li><b>Aim :</b> <img src="image.php?tex=<?php echo htmlspecialchars($profil['membre_aim'], ENT_QUOTES); ?>"/></li>
<?php
}
?>
</ul>
</div>
|
On rajoute la biographie, la signature, et on clôt la page.
Code : PHP 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | <!--signature et fin//-->
<div class="profil_ligne">
<h2>Signature</h2>
<?php echo htmlspecialchars($profil['membre_signature'], ENT_QUOTES); ?>
</div>
<div class="profil_ligne">
<h2>Biographie</h2>
<?php echo htmlspecialchars($profil['membre_biographie'], ENT_QUOTES); ?>
</div>
</div>
<?php
include('../includes/bas.php');
mysql_close();
?>
|
On peut enfin passer à
image.php.
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
/*
Neoterranos & LkY
Page image.php
Génère une image d'un texte passé en GET['tex'].
Quelques indications (utiliser l'outil de recherche et rechercher les mentions données) :
Liste des fonctions :
--------------------------
Aucune fonction
--------------------------
Liste des informations / erreurs :
--------------------------
Aucune information / erreur
--------------------------
*/
header ("Content-type: image/png");
$count = strlen($_GET['tex']);
$image = imagecreate($count*9, 18);
if(function_exists(imagecolorallocatealpha))
{
$blanc = imagecolorallocatealpha($image, 255, 255, 255, 127);
}
else
{
$blanc = imagecolorallocate($image, 255, 255, 255, 127);
}
$noir = imagecolorallocate($image, 0, 0, 0);
imagestring($image, 5, 1, 1, htmlspecialchars($_GET['tex'], ENT_QUOTES), $noir);
imagepng($image);
?>
|
Le plus dur dans cette page a été de définir la taille de l'image souhaitée, ni trop grosse, ni trop petite, avec la police que j'ai choisie, chaque caractère fait 9 pixels de large : ainsi, nous sommes tranquilles.
La fonction
function_exists()
vérifie qu'une fonction existe bien dans votre version de PHP.
Nous avons enfin notre dernier point respecté.
Voilà un profil qui ressemble à celui du SdZ comme deux gouttes d'eau se ressemblent, ce n'est pas par manque d'imagination que je vous propose cela, mais simplement parce que je sais que ce mode d'affichage plaît à pas mal de monde.

Passons au CSS : pour le moment, cette pauvre page souffre un peu de son design.
Code : CSS 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 | .profil_cellule_float {
float: left;
width: 47%;
border: 1px solid #CCDFEF;
max-height: 30%;
margin-bottom: 1%;
margin-left: 1%;
margin-right: 1%;
height: 250px;
}
.profil_cellule {
margin-left: 49%;
margin-bottom: 1%;
margin-right: 1%;
width: 47%;
border: 1px solid #CCDFEF;
height: 250px;
}
.profil_ligne {
width: 95%;
margin-left: 1%;
border: 1px solid #CCDFEF;
margin-bottom: 1%;
}
.avatar {
margin-left: 10%;
float: left;
min-width: 150px;
min-height: 130px;
}
h3 {
text-decoration: underline;
color: #507080;
font-family:"trebuchet ms", verdana, sans-serif;
font-variant:small-caps;
font-weight:bold;
font-size:17px;
}
|
Vous l'avez constaté, sur cette page, la réelle difficulté devrait être le CSS, et encore, c'est pour cela que je ne m'étends pas en explications, je ne voudrais pas que vous croyiez que je vous prends pour des idiots.

Bien, vous avez enfin des listes de vos membres, des connectés, etc., elles sont assez vides, car le système est pour le moment basique, c'est à vous de le modifier ; mais dans la partie II, nous les remplirons un peu plus, quant à la visualisation de profils, vous voyez que ce n'était pas si difficile, nous verrons en partie II comment sécuriser certaines informations telles que le mail ou la date de naissance.
Sur ce, attaquons l'édition de profil !
Informations sur le tutoriel