Comment faire un affichage page par page en PHP

Lorsque l'on utilise une base de données, il arrive souvent que l'on fasse des requêtes sur cette base de données et que l'on obtienne des dizaines voir des centaines de résultats.
Jusqu'ici, vous faisiez une boucle while pour parcourir l'ensemble de vos résultats et vous les affichiez sur une même page.

C'était fort inesthétique.
En effet, une page de 3 km de long ne fait plaisir à personne et est toujours très longue à charger.

Ce tutorial va donc vous apprendre à créer une barre de navigation identique à celle présente sur ce site pour le forum et la home (en bas des news).

Avant de rentrer dans la rédaction de cette barre de navigation, nous allons faire un petit point sur la syntaxe SQL.
En effet, vous avez déjà que le SQL permet d'ordonner les résultats grâce à l'ORDER BY (cf. cours Afficher les données provenant de votre base).

En revanche, ce que vous ne savez peut être pas, c'est que le SQL permet, lors d'une sélection sur une table, de limiter le nombre de résultats obtenus grâce à la commande LIMIT.

Afin de concrétiser tout cela et donc de voir comment fonctionne cette commande LIMIT, nous allons créer une table catalogue permettant de lister tous les livres d'une bibliothèque par exemple.

On pourrait avoir alors la structure suivante :

table_catalogue.sql
CREATE TABLE catalogue (
id int(11) NOT NULL auto_increment,
titre text NOT NULL,
description text NOT NULL,
PRIMARY KEY (id)
) TYPE=MyISAM;


Remplissons alors cette table avec différents livres :

contenu_de_catalogue.sql
INSERT INTO catalogue VALUES (1, 'Le php facile', 'La future référence :)');
INSERT INTO catalogue VALUES (2, 'Professional PHP4 XML', 'Tout pour apprendre l'XML');
INSERT INTO catalogue VALUES (3, 'PHP et MySQL pour les nuls', 'Pour les débutants');
INSERT INTO catalogue VALUES (4, 'PHP précis et concis', 'Un livre sympa :)');
INSERT INTO catalogue VALUES (5, 'Dreamweaver MX', 'Pour les allergiques du notepad');
INSERT INTO catalogue VALUES (6, 'Advanced PHP for Web Professionals', 'Un bon livre pour ceux qui ne rigolent pas');
INSERT INTO catalogue VALUES (7, 'Je débute en PHP 4', 'Pour nous :)');
INSERT INTO catalogue VALUES (8, 'PHP Bible', 'Pour les fanas de religion');
INSERT INTO catalogue VALUES (9, 'Advanced PHP for Flash', 'Pour les graphistes');
INSERT INTO catalogue VALUES (10, 'Essential PHP fast', 'Un livre pour les pressés');


Déjà çà de fait.
Nous allons donc maintenant pouvoir nous pencher sur la compréhension de la commande LIMIT.

Aujourd'hui, vous devriez savoir faire une requête simple permettant d'afficher tous les livres de cette bibliothèque sur une même page WEB, et ce, en classant les livres par ordre alphabétique, ce qui donnerait le code suivant :

index.php
<html>
<head>
<title>Les livres de la bibliothèque</title>
</head>

</body>
Les différents livres de la bibliothèque :<br /><br />
<?php
// on se connecte à notre base
$base = mysql_connect ('serveur', 'login', 'password');
mysql_select_db ('nom_base', $base);

// Préparation de la requête
$sql = 'SELECT titre, description FROM catalogue ORDER BY titre ASC';

// on lance la requête (mysql_query) et on impose un message d'erreur si la requête ne se passe pas bien (or die)
$req = mysql_query($sql) or die('Erreur SQL !<br />'.$sql.'<br />'.mysql_error());

// on compte le nombre de livre contenu dans la base de données
$nb_livres = mysql_num_rows($req);

if ($nb_livres == 0) {
echo 'Aucun livre enregisté.';
}
else {
echo '<table><tr><td><td>Description</td></tr>';
// on va scanner tous les tuples un par un
while ($data = mysql_fetch_array($req)) {
// on affiches les résultats dans la <table>
echo '<tr><td><td>' , htmlentities(trim($data['description'])) , '</td></tr>';
}
echo '</table>';
}
// on libère l'espace mémoire alloué pour cette requête
mysql_free_result ($req);
// on ferme la connexion à la base de données.
mysql_close ();
?>

</body>
</html>




Et ceci affichera quelque chose ressemblant à :

Titre du livreDescription
Advanced PHP for FlashPour les graphistes
Advanced PHP for Web ProfessionalsUn bon livre pour ceux qui ne rigolent pas
Dreamweaver MXPour les allergiques du notepad
Essential PHP fastUn livre pour les pressés
Je débute en PHP 4Pour nous :)
Le php facileLa future référence :)
PHP BiblePour les fanas de religion
PHP et MySQL pour les nulsPour les débutants
PHP précis et concisUn livre sympa :)
Professional PHP4 XMLTout pour apprendre l'XML


Introduisons alors le LIMIT.

En fait LIMIT va vous permettre de limiter le nombre de résultats à afficher d'une requête SQL donnée.
En effet, vous allez pourvoir, par exemple, n'afficher que les 3 premiers livres de la table.


Reprenons alors le code précédent, et changeons la requête SQL par la requête suivante :

select avec limit
SELECT titre, description FROM catalogue ORDER BY titre ASC LIMIT 0,3


Et ceci affichera quelque chose ressemblant à :

Titre du livreDescription
Advanced PHP for FlashPour les graphistes
Advanced PHP for Web ProfessionalsUn bon livre pour ceux qui ne rigolent pas
Dreamweaver MXPour les allergiques du notepad


Comprenons cette requête :
  • on sélectionne les titre et les descriptions de livres (SELECT titre, description)
  • on fait cette sélection sur la table catalogue (FROM catalogue)
  • on ordonne les résultats dans l'ordre alphabétique des titres (BY titre ASC)
  • on sélectionne juste 3 livres à partir du 0 + 1 livre, soit du premier livre (LIMIT 0,3)


Attention le 0 peut être trompeur.

En effet, il faut lire en fait 0 + 1 (soit 1) : on sélectionne "en français" à partir du premier livre, mais "en SQL", on sélectionne à partir du livre 0.

Encore un exemple :

Reprenons encore une fois le code précédent mais avec cette fois ci le code suivant pour la requête SQL :

select avec limit
SELECT titre, description FROM catalogue ORDER BY titre ASC LIMIT 4,3


Si on y réfléchit deux minutes, théoriquement, cette requête SQL nous dit quoi ?

Et bien, nous allons sélectionner les titres et les descriptions de certains livres qui sont stockés dans la table catalogue.
Ensuite nous allons prendre ces livres dans l'ordre alphabétique de leur titre, puis nous allons n'en sélectionner que quelques uns.
Lesquels ?
Et bien, nous allons sélectionner 3 livres (le 3 après la virgule), et ce, à partir du 4+1 ème livre, soit du cinquième.

On devrait donc se retrouver avec les livres suivants :

<table width="500" border="0" cellspacing="0" cellpadding="4"><tr><td>:: Titre du livre ::</td><td>:: Description ::</td></tr><tr><td>Le php facile</td><td>La future référence</td></tr><tr><td>PHP Bible</td><td>Pour les fanas de religion</td></tr></table>

Et en exécutant le script, nous obtenons bien ce que nous avions prévus.

En résumé pour le LIMIT x,y :
On sélectionne y éléments et ce, à partir du (x+1) ème élément.
Bien sur, tout dépend de l'ordre dans lequel on fait notre requête : ORDER BY ... ASC ou ORDER BY ... DESC (ordre croisant ou décroissant).

En effet, si on a un ORDER BY ... DESC (ordre décroissant), on prendra en fait les y éléments qui arrivent juste avant le (x+1) ème élément.

Naturellement, à ce point du cours, vous devriez normalement voir plus ou moins vers quoi on avance.

En effet, notre affichage page par page va en fait refaire plusieurs fois la même requête SQL avec un LIMIT x,y sauf qu'à chaque fois, et donc à chaque page, le paramètre x va changer.

Admettons que notre table comporte 50 éléments et que l'on désire afficher 10 résultats sur chaque page.

On aura en fait notre requête SQL qui va légèrement varier suivant la page que l'on affiche.
Et ce qui va varier, et bien c'est le LIMIT de notre requête (plus particulièrement le x), comme ceci :
Page 1 => LIMIT 0,10
Page 2 => LIMIT 10,10
Page 3 => LIMIT 20,10
Page 4 => LIMIT 30,10
Page 5 => LIMIT 40,10

Il s'agit maintenant de réfléchir pour pourvoir mettre en oeuvre tout ceci via une barre de navigation contenant des liens du genre :

Pages : << 1 - 2 - 3 - 4 - 5 - 6 >>


Et cette barre de navigation permettra à l'utilisateur ne naviguer simplement entre les différentes pages (le << étant un lien permettant de revenir directement à la première page, le >> à la dernière.

Bon alors là il va falloir s'accrocher.
On va maintenant voir le code complet de notre page permettant de voir l'affichage page par page et qui comprend donc la fameuse fonction permettant d'afficher la barre de navigation.

On aura alors (cependant, je vous encourage vivement à lire tout d'abord le code de la page WEB, puis ensuite d'essayer de comprendre le fonctionnement de la fonction créant la barre de navigation) :

index.php
<?php
function barre_navigation ($nb_total,
$nb_affichage_par_page,
$debut,
$nb_liens_dans_la_barre) {

$barre = '';

// on recherche l'URL courante munie de ses paramètre auxquels on ajoute le paramètre 'debut' qui jouera le role du premier élément de notre LIMIT
if ($_SERVER['QUERY_STRING'] == "") {
$query = $_SERVER['PHP_SELF'].'?debut=';
}
else {
$tableau = explode ("debut=", $_SERVER['QUERY_STRING']);
$nb_element = count ($tableau);
if ($nb_element == 1) {
$query = $_SERVER['PHP_SELF'].'?'.$_SERVER['QUERY_STRING'].'&debut=';
}
else {
if ($tableau[0] == "") {
$query = $_SERVER['PHP_SELF'].'?debut=';
}
else {
$query = $_SERVER['PHP_SELF'].'?'.$tableau[0].'debut=';
}
}
}

// on calcul le numéro de la page active
$page_active = floor(($debut/$nb_affichage_par_page)+1);
// on calcul le nombre de pages total que va prendre notre affichage
$nb_pages_total = ceil($nb_total/$nb_affichage_par_page);

// on calcul le premier numero de la barre qui va s'afficher, ainsi que le dernier ($cpt_deb et $cpt_fin)
// exemple : 2 3 4 5 6 7 8 9 10 11 << $cpt_deb = 2 et $cpt_fin = 11
if ($nb_liens_dans_la_barre%2==0) {
$cpt_deb1 = $page_active - ($nb_liens_dans_la_barre/2)+1;
$cpt_fin1 = $page_active + ($nb_liens_dans_la_barre/2);
}
else {
$cpt_deb1 = $page_active - floor(($nb_liens_dans_la_barre/2));
$cpt_fin1 = $page_active + floor(($nb_liens_dans_la_barre/2));
}

if ($cpt_deb1 <= 1) {
$cpt_deb = 1;
$cpt_fin = $nb_liens_dans_la_barre;
}
elseif ($cpt_deb1>1 && $cpt_fin1<$nb_pages_total) {
$cpt_deb = $cpt_deb1;
$cpt_fin = $cpt_fin1;
}
else {
$cpt_deb = ($nb_pages_total-$nb_liens_dans_la_barre)+1;
$cpt_fin = $nb_pages_total;
}

if ($nb_pages_total <= $nb_liens_dans_la_barre) {
$cpt_deb=1;
$cpt_fin=$nb_pages_total;
}

// si le premier numéro qui s'affiche est différent de 1, on affiche << qui sera un lien vers la premiere page
if ($cpt_deb != 1) {
$cible = $query.(0);
$lien = '<A HREF="'.$cible.'">&lt;&lt;</A>&nbsp;&nbsp;';
}
else {
$lien='';
}
$barre .= $lien;

// on affiche tous les liens de notre barre, tout en vérifiant de ne pas mettre de lien pour la page active
for ($cpt = $cpt_deb; $cpt <= $cpt_fin; $cpt++) {
if ($cpt == $page_active) {
if ($cpt == $nb_pages_total) {
$barre .= $cpt;
}
else {
$barre .= $cpt.'&nbsp;-&nbsp;';
}
}
else {
if ($cpt == $cpt_fin) {
$barre .= "<A HREF='".$query.(($cpt-1)*$nb_affichage_par_page);
$barre .= "'>".$cpt."</A>";
}
else {

$barre .= "<A HREF='".$query.(($cpt-1)*$nb_affichage_par_page);
$barre .= "'>".$cpt."</A>&nbsp;-&nbsp;";
}
}
}

$fin = ($nb_total - ($nb_total % $nb_affichage_par_page));
if (($nb_total % $nb_affichage_par_page) == 0) {
$fin = $fin - $nb_affichage_par_page;
}

// si $cpt_fin ne vaut pas la dernière page de la barre de navigation, on affiche un >> qui sera un lien vers la dernière page de navigation
if ($cpt_fin != $nb_pages_total) {
$cible = $query.$fin;
$lien = '&nbsp;&nbsp;<A HREF="'.$cible.'">&gt;&gt;</A>';
}
else {
$lien='';
}
$barre .= $lien;

return $barre;
}
?>

<html>
<head>
<title>Les livres de la bibliothèque</title>
</head>

</body>
Les différents livres de la bibliothèque :<br /><br />
<?php
// on se connecte à notre base
$base = mysql_connect ('serveur', 'login', 'nom_base');
mysql_select_db ('nom_base', $base);

// on prépare une requête permettant de calculer le nombre total d'éléments qu'il faudra afficher sur nos différentes pages
$sql = 'SELECT count(*) FROM catalogue';

// on exécute cette requête
$resultat = mysql_query($sql) or die('Erreur SQL !<br />'.$sql.'<br />'.mysql_error());

// on récupère le nombre d'éléments à afficher
$nb_total = mysql_fetch_array($resultat);

// on teste si ce nombre de vaut pas 0
if (($nb_total = $nb_total[0]) == 0) {
echo 'Aucune réponse trouvée';
}
else {
echo '<table><tr><td><td>Description</td></tr>';

// sinon, on regarde si la variable $debut (le x de notre LIMIT) n'a pas déjà été déclarée, et dans ce cas, on l'initialise à 0
if (!isset($_GET['debut'])) $_GET['debut'] = 0;

$nb_affichage_par_page = 1;

// Préparation de la requête avec le LIMIT
$sql = 'SELECT titre, description FROM catalogue ORDER BY titre ASC LIMIT '.$_GET['debut'].','.$nb_affichage_par_page;

// on exécute la requête
$req = mysql_query($sql) or die('Erreur SQL !<br />'.$sql.'<br />'.mysql_error());

// on va scanner tous les tuples un par un
while ($data = mysql_fetch_array($req)) {
// on affiches les résultats dans la <table>
echo '<tr><td><td>' , htmlentities(trim($data['description'])) , '</td></tr>';
}

// on libère l'espace mémoire alloué pour cette requête
mysql_free_result ($req);
echo '</table><br />';

// on affiche enfin notre barre
echo '[b]'.barre_navigation($nb_total, $nb_affichage_par_page, $_GET['debut'], 3).'[/b]';
}
// on libère l'espace mémoire alloué pour cette requête
mysql_free_result ($resultat);
// on ferme la connexion à la base de données.
mysql_close ();
echo '</table><br />';
?>

</body>
</html>


Ouf :)

J'espère que vous n'avez pas eu une crise cardiaque en lisant ceci.

Enfin, sachez que cette barre de navigation peut s'appliquer à n'importe quelle requête SQL et que vous désirez faire un affichage page par page.

A titre d'info, cette barre de navigation est utilisée sur ce même site pour le forum et les news.
LoadingChargement en cours