Pour partager cette vidéo sur les réseaux sociaux ou sur un site, voici son url :
Sujets que vous pourriez aussi aimer :
Naviguer grâce à une pagination
Dans cette
formation PHP , nous proposons d'aboutir les travaux réalisés lors des deux formations précédentes. Dans le premier volet, nous avions réalisé la
liaison dynamique entre deux
listes déroulantes . De fait, la seconde liste déroulante se remplit en fonction du choix émis dans la première. Mais à restitution des résultats issus de la
base de données MySql , du fait du
PostBack , nous perdions l'affichage des réglages et choix émis. Nous avions donc introduit la
technologie Ajax dans le deuxième volet. Cette technique nous avait permis d'externaliser le
code Php de traitement des données. Désormais, les résultats correspondant aux critères recoupés, sont restitués en lieu et place, sans imposer le rechargement de la page.
Mais nous avions dû limiter le nombre d'enregistrements. Seules les 10 premières idées de sorties, correspondant aux choix du département et de la ville sont extraites, faute de place. C'est pourquoi dans cette formation, nous proposons de bâtir un
système de pagination . Ainsi, l'internaute pourra naviguer au travers des pages pour consulter à loisir, l'intégralité des informations extraites.
Sources et présentation de la problématique
Nous devons commencer par récupérer les travaux réalisés dans les deux formations précédentes.
La décompression conduit au fichier de la page Web principale. Il est nommé
index.php . Il est accompagné de ses ressources externes dans les sous dossiers. De même, à la racine, vous trouvez le
fichier reponse.php . Il s'agit du
code Php externalisé pour les
traitements Ajax , ceux qui consistent à restituer les résultats sans recharger la page Web.
Pour mener à bien ces travaux, la
base de données ids doit exister. Nous l'avions créée dans les formations précédentes. Si vous ne la possédez pas, vous devez la créer.
Elle doit proposer une
table nommée
liste_id . Et cette dernière doit offrir les champs liste_num, liste_nom, liste_activite, liste_dep et liste_ville. Le
champ liste_num est la colonne de la
clé primaire . Il doit être
auto-incrémenté . Dès lors vous pourrez y importer les données proposées dans le
sous dossier bdd , au
format Sql .
Un compte utilisateur doit lui être associé avec les privilèges administrateurs :
Nom d'utilisateur : codePHP,
Nom d'hôte : Votre adresse locale, ici : 127.0.0.1,
Mot de passe : php123bd.
Ainsi, grâce à ces informations, nos
instructions Php pourront accéder aux données de la
base MySql .
Et comme vous le savez désormais fort bien, ce projet doit être référencé dans
EasyPhp . De plus, les deux serveurs doivent être démarrés.
La page d'accueil de l'application serveur est alors accessible par simple clic sur le lien du projet.
Cliquer sur le lien de l'application pour accéder à sa page d'accueil,
Déployer la liste déroulante qui se propose et choisir un département,
Instantanément, la liste liée des villes correspondantes se construit.
Déployer cette seconde liste déroulante et choisir une ville,
Les premiers résultats correspondant à ces deux critères recoupés sont automatiquement extraits par le
code Php . La page Web n'a pas été réinitialisée du fait d'un PostBack, grâce à la
technologie AJAX . Nous devons désormais proposer une petite barre de navigation, en dessous de ces résultats. Elle doit offrir des numéros cliquables, correspondant aux pages à atteindre, pour visualiser la suite de l'extraction. A ce titre, vous notez la présence d'une petite zone de saisie (Contrôle Html Input) entre les deux
listes déroulantes . Sa valeur par défaut est calée sur le chiffre 1. Nous l'exploiterons pour y inscrire le numéro de la page appelée. Comme ce contrôle est placé dans le
formulaire Html , sa valeur sera transmise au
code Php , en même temps que les choix émis par le biais des
listes déroulantes . Bien sûr, nous masquerons ce contrôle. Il est utile pour des finalités techniques et n'intéresse pas l'internaute.
A la racine du dossier de décompression, cliquer droit sur le fichier index.php ,
Dans le menu contextuel, choisir de l'ouvrir avec un éditeur comme le Notepad++,
Vous notez la présence de la
section Php en entête de code. C'est elle qui permet de relier les
listes déroulantes en fonction du choix effectué dans la première des deux. En introduction, vous remarquez la construction de la
chaîne de connexion à la base de données MySql , selon les identifiants mentionnés plus haut :
<?php
$liaison = mysqli_connect("127.0.0.1", "codePHP", "php123bd");
mysqli_select_db($liaison, "ids");
$requete = "SELECT DISTINCT liste_ville, liste_dep FROM liste_id ORDER BY liste_dep, liste_ville;";
$retours = mysqli_query($liaison, $requete);
...
Plus bas dans le
code Html , plus précisément à partir de la ligne 104 pour un éditeur Notepad, débute la construction du
formulaire Html . Il englobe les
contrôles de listes déroulantes , ainsi que la zone de saisie pour la
pagination . Cette dernière possède l'identifiant et le nom
num_page .
Dans sa propriété style, ajouter son attribut visibility réglé sur hidden , comme suit :
?>
</select>
<input type="text" name="num_page" id="num_page" value="1" style="width:10px;visibility:hidden; " />
<div id="calque_ville" class="liste_div" style="float:right;">
</div>
Ainsi, la zone de texte reste exploitable mais n'est plus visible pour l'internaute.
Enregistrer les modifications (CTRL + S)
Basculer sur le navigateur Web,
Recharger la page en validant sa barre d'adresse par la touche Entrée,
Sélectionner un département à l'aide de la liste déroulante,
Puis, sélectionner une ville dans la liste déroulante dépendante auto-construite,
Comme précédemment, les premiers résultats de l'extraction correspondant aux critères recoupés s'affichent. Cependant, la zone de texte qui était située entre les deux listes déroulantes a disparu.
Il va désormais s'agir de la renseigner dynamiquement et d'exploiter son contenu par le
code Php , pour réaliser les extractions concordantes.
Revenir dans le code de la page index.php,
Comme l'indique l'
évènement onChange de la
liste déroulante choix_dep , c'est la
fonction Javascript charger_villes qui s'occupe de construire la seconde liste déroulante en fonction du choix réalisé dans la première. Cette fonction intervient à partir de la ligne 152 pour un éditeur Notepad. Et c'est de nouveau l'
évènement onChange , cette fois associé à la liste déroulante des villes, qui appelle la
fonction Javascript recolter .
Cette fonction intervient plus haut dans la page, à partir de la ligne 59 pour un éditeur Notepad.
...
<link href='styles/mef.css' rel='stylesheet' type='text/css' />
<script src="js/prototype.js" type="text/javascript"></script>
<script language='javascript' id='cible' src='js/villes_dep.js'></script>
<script language='javascript' type="text/javascript">
function recolter()
{
document.getElementById("formulaire").request({
onComplete:function(transport){
document.getElementById('colonne_gauche').innerHTML = transport.responseText;
}
});
}
</script>
</head>
...
Elle exploite le
script externe Ajax déclaré en référence pour transmettre les valeurs du formulaire et déclencher le
code serveur Php externalisé. Ce dernier est écrit dans le
fichier reponse.php qui est désigné par l'
attribut action du formulaire Web. Toute cette construction est fonctionnelle. Nous devons l'exploiter sans l'altérer. Nos travaux doivent se concentrer précisément sur ce
code Php externalisé .
Compter les résultats d'une extraction SQL
Pour connaître le nombre de pages à proposer dans la navigation, nous devons connaître le nombre d'enregistrements correspondant aux critères recoupés. Il s'agit d'exécuter une
requête sensiblement identique à celle conçue dans la
page reponse.php . Mais nous devons exploiter la
fonction Sql Count , par exemple sur le champ de la clé primaire. Comme son nom l'indique, elle compte les enregistrements retournés.
A la racine du dossier de décompression, cliquer droit sur le fichier reponse.php ,
Dans le menu contextuel, choisir de l'ouvrir avec un éditeur comme le Notepad++,
Nous devons conserver tout le code actuel consistant à restituer les premiers résultats. Néanmoins, nous adapterons plus tard la syntaxe de la
requête SQL , de manière à isoler seulement les résultats de la page concernée. Pour l'instant, nous devons prélever le nombre d'enregistrements concordants. Et pour ce faire, nous avons donc besoin d'exécuter une
requête supplémentaire. La syntaxe de la première peut d'ailleurs être prélevée pour être adaptée plus simplement.
Dans le code Php , ajouter les lignes inscrites en gras dans l'extrait proposé ci-dessous :
<?php
if(isset($_POST["choix_dep"]) && isset($_POST["choix_ville"]))
{
$liaison2 = mysqli_connect("127.0.0.1", "codePHP", "php123bd");
mysqli_select_db($liaison2, "ids");
$le_dep = $_POST["choix_dep"];
$la_ville = $_POST["choix_ville"];
$requete_nb = "SELECT COUNT(liste_num) AS NBP FROM liste_id WHERE liste_dep='".utf8_decode($le_dep)."' AND liste_ville='".utf8_decode($la_ville)."'";
$retours_nb = mysqli_query($liaison2, $requete_nb);
$tab_nb = mysqli_fetch_array($retours_nb);
$nb_pages=$tab_nb["NBP"];
$requete = "SELECT liste_nom, liste_activite FROM liste_id WHERE liste_dep='".utf8_decode($le_dep)."' AND liste_ville='".utf8_decode($la_ville)."' ORDER BY liste_nom LIMIT 0,10;";
$retours = mysqli_query($liaison2, $requete);
$chaine = "";
while($retour = mysqli_fetch_array($retours))
{
$chaine .= "<div style='float:left; width:190px; margin-left:10px; font-size:12px; text-align:left;'>".utf8_encode(str_replace("#", "'", $retour["liste_nom"]))."</div><div style='float:left; width:130px; font-size:10px; text-align:left;'>".utf8_encode(str_replace("#", "'", $retour["liste_activite"]))."</div><br/>";
}
$chaine.= "<div style='float:left; width:320px; margin-right:10px; font-size:12px; text-align:right;'>".$nb_pages."</div>";
print($chaine);
mysqli_close($liaison2);
}
?>
Grâce à la
fonction SQL COUNT , nous comptons le nombre d'enregistrements résultants. Comme pour la requête précédente, ils sont issus de la
table liste_id (FROM liste_id). Ils doivent recouper les critères (clause WHERE) sur le choix du département et de la ville. Le résultat numérique est stocké dans un champ nommé à la volée
NBP grâce à la
clause AS (AS NBP). C'est par ce nom que nous pourrons accéder à son contenu.
Ensuite et comme toujours, nous exploitons la
fonction Php mysqli_query pour exécuter cette requête sur la base de données. Le résultat est enregistré sous forme d'objet sous le
nom de variable $retours_nb . Nous exploitons alors la
fonction Php mysqli_fetch_array sur cet objet pour découper l'information en
tableau de variables . Chaque rangée ainsi créée correspond à l'un des champs. Cette requête est statistique. Elle n'en retourne qu'un seul. Et ce champ est nommé
NBP . Nous n'avons plus qu'à le désigner dans le tableau de variables ($nb_pages = $tab_nb["NBP"]). C'est désormais la
variable $nb_pages qui stocke cette information.
Nous l'exploitons après la
boucle While restituant les enregistrements, pour afficher le nombre de résultats, dans un calque Html (balise Div).
Enregistrer les modifications et basculer sur le navigateur Web,
Recharger la page en validant sa barre d'adresse avec la touche Entrée du clavier,
Avec la première liste déroulante, choisir un département, par exemple : 26-Drome,
Avec la seconde liste qui se propose, choisir une ville, par exemple : Valence,
Les dix premiers enregistrements sont extraits comme nous l'avions codé lors des formations précédentes. Mais désormais, une indication supplémentaire est retournée. Il s'agit du nombre de résultats, affiché en bas de page, comme l'indique la capture ci-dessus. A ce stade, la
variable $nb_pages porte mal son nom. Elle ne correspond pas au nombre de pages mais au nombre d'enregistrements. Il s'agit d'un résultat intermédiaire que nous allons retravailler.
Compter les pages de la navigation
Pour transformer ce résultat en nombre de pages à offrir à l'internaute, le calcul est très simple. 10 enregistrements sont proposés par page. C'est d'ailleurs ce que mentionne la
clause LIMIT de la
requête SQL d'extraction (...ORDER BY liste_nom LIMIT 0,
10 ;";). Il suffit donc de diviser la valeur retournée grâce à la
requête SQL COUNT par 10, puis de prélever le nombre entier directement supérieur. C'est la
fonction Php ceil qui permet d'arrondir un nombre décimal au nombre entier supérieur.
Revenir dans le code de la page reponse.php,
Puis, ajouter le calcul suivant pour la variable $nb_pages ,
...
$requete_nb = "SELECT COUNT(liste_num) AS NBP FROM liste_id WHERE liste_dep='".utf8_decode($le_dep)."' AND liste_ville='".utf8_decode($la_ville)."'";
$retours_nb = mysqli_query($liaison2, $requete_nb);
$tab_nb = mysqli_fetch_array($retours_nb);
$nb_pages=$tab_nb["NBP"];
$nb_pages = ceil($nb_pages/10);
...
Enregistrer les modifications et basculer sur le navigateur Web,
Recharger la page en validant sa barre d'adresse avec la touche Entrée du clavier,
Avec la première liste déroulante, choisir le département 26-Drome comme précédemment,
De même et à titre de comparaison, choisir ensuite la ville de Valence,
Nous obtenons cette fois le chiffre 13. 13 pages sont effectivement nécessaires pour naviguer au travers des 127 résultats, à raison de 10 enregistrements par page.
Il suffit désormais de fabriquer une boucle partant du chiffre 1 et rejoignant celle limite supérieure variable, pour énumérer chacune des pages à proposer dans la navigation.
Revenir dans le code de la page reponse.php,
Après la boucle while, adapter l'affectation de la variable $chaine , comme suit :
...
$chaine = "";
while($retour = mysqli_fetch_array($retours))
{
$chaine .= "<div style='float:left; width:190px; margin-left:10px; font-size:12px; text-align:left;'>".utf8_encode(str_replace("#", "'", $retour["liste_nom"]))."</div><div style='float:left; width:130px; font-size:10px; text-align:left;'>".utf8_encode(str_replace("#", "'", $retour["liste_activite"]))."</div><br/>";
}
$chaine.= "<div style='float:left; width:320px; margin-right:10px; font-size:12px; text-align:right;'>";
for($la_page=1; $la_page<=$nb_pages; $la_page++)
{
$chaine.= "<div style='margin:5px; float:left; cursor:pointer;' onClick='document.getElementById(\"num_page\").value = \"".$la_page."\"; recolter();'>".$la_page."</div>";
}
$chaine.= "</div>";
print($chaine);
mysqli_close($liaison2);
}
?>
Nous conservons le calque conteneur que nous ouvrons avant d'initier une
boucle for . Nous refermons d'ailleurs ce calque après cette boucle. Ce
traitement itératif consiste à parcourir l'ensemble des pages jusqu'à la dernière ($la_page<=$nb_pages). Et pour chacune, nous affichons son numéro dans un calque indépendant assemblé à la volée, à chaque passage dans la boucle. L'
évènement Javascript onClick de chacun de ces calques ainsi construits, est particulièrement important. Il permet tout d'abord d'inscrire le numéro de la page appelée dans le
contrôle masqué num_page . Puis il appelle dans la foulée la
fonction Javascript recolter . Souvenez-vous, cette dernière réalise la transaction avec le serveur en lui soumettant les valeurs du formulaire. De cette manière, le numéro de page à afficher pour restituer les résultats correspondants est transmis.
Enregistrer les modifications et basculer sur le navigateur Web,
Recharger la page en validant sa barre d'adresse avec la touche Entrée,
Choisir le département 26-Drome et la ville de Valence,
Comme vous le remarquez, tous les numéros de pages sont ainsi proposés en-dessous des résultats de l'extraction, correspondant aux critères recoupés du département et de la ville. Pour 127 enregistrements, nous obtenons fort logiquement une proposition de navigation sur 13 pages. Ces numéros sont cliquables et transmettent cette indication de
pagination , en même temps que les informations des listes déroulantes. Nous devons l'exploiter pour adapter les résultats à la demande.
Extraction SQL sur indice de pagination
L'adaptation est triviale car l'essentiel du
code Php existe déjà . Il suffit d'ajuster la
clause LIMIT de la seconde
syntaxe SQL . Elle extrait bien 10 enregistrements comme nous le souhaitons. Mais elle débute pour l'instant cette extraction à partir du premier (indice 0). C'est cet indice que nous devons dynamiquement adapter, en fonction de l'information de page transmise.
La page 2 doit débuter la restitution à partir du 11
ème enregistrement situé à l'indice 10. La page 3 doit débuter la restitution à partir du 21
ème enregistrement situé à l'indice 20 et ainsi de suite. L'opération sur la variable de page transmise est simple :
(Num_page-1)*10 . C'est ce calcul stocké en variable que nous devons exploiter comme point de départ dans la
clause LIMIT de la
syntaxe SQL .
Revenir dans le code de la page reponse.php,
Dans la seconde requête et juste au-dessus, adapter le code Php comme suit :
...
$nb_pages=$tab_nb["NBP"];
$nb_pages = ceil($nb_pages/10);
$depart=1;
if(isset($_POST["num_page"]) && $_POST["num_page"]!="")
$depart = $_POST["num_page"];
$depart = ($depart-1)*10;
$requete = "SELECT liste_nom, liste_activite FROM liste_id WHERE liste_dep='".utf8_decode($le_dep)."' AND liste_ville='".utf8_decode($la_ville)."' ORDER BY liste_nom LIMIT ".$depart." ,10;";
$retours = mysqli_query($liaison2,$requete);
$chaine = "";
while($retour = mysqli_fetch_array($retours))
{
...
Nous déclarons la
variable $depart que nous initialisons sur la première page. Nous prenons soin de tester l'existence de l'indice de page transmis, grâce à la
fonction Php isset . S'il existe, nous le stockons dans la
variable $depart . Puis nous réalisons le calcul de positionnement sur le premier enregistrement à restituer, pour la page demandée. Enfin, nous adaptons la
clause LIMIT de la
syntaxe SQL en remplaçant le point de départ statique par la variable dynamique.
Un dernier ajustement est nécessaire. Au changement de ville, le
contrôle num_page conserve l'ancienne valeur qui lui a été passée. Pourtant, la restitution doit repartir du premier enregistrement. Nous devons réinitialiser sa valeur dans la fonction
Javascript charger_villes de la
page index.php . C'est elle qui construit dynamiquement la liste déroulante dépendante des villes. Cette réinitialisation doit intervenir dans l'
évènement onChange , avant l'appel de la
fonction recolter .
Enregistrer les modifications,
Revenir dans le code de la page index.php,
Dans la fonction Javascript charger_villes , adapter le code de la construction de la liste déroulante, comme suit :
...
nb_villes = tab_villes.length;
//alert(nb_villes);
chaine_liste = "<select id='choix_ville' name='choix_ville' class='liste' onChange='verif_villes(\"" + dep_texte +"\"); document.getElementById(\"num_page\").value = 1; recolter();'>";
chaine_liste += "<option value='Sélection'>Sélectionner une ville</option>";
for(var defil=0; defil<nb_villes; defil++)
{
...
Enregistrer les modifications et basculer sur le navigateur Internet,
Recharger la page Web en validant sa barre d'adresse par la touche Entrée du clavier,
Choisir le département 26-Drome avec la première liste déroulante,
Choisir la ville de Montélimar avec la seconde liste déroulante,
Cliquer sur les petits numéros pour faire défiler les pages,
Comme vous le constatez, nous avons bâti un
système de pagination tout à fait fonctionnel. Dans un espace réduit, il permet à l'internaute d'accéder à tous les enregistrements répondant à ses critères. De plus, si vous changez de ville, la restitution redémarre bien depuis le premier enregistrement.
Indicateur de position
Un détail doit être réglé. Au fil de la navigation, aucun indicateur ne renseigne sur la position en cours. Il devient compliqué de se situer dans la
pagination . Pour pallier ce défaut, nous proposons de modifier la couleur du numéro correspondant à la page en cours. Pour cela, il suffit de régler l'
attribut Html color dans la
balise Div . Mais cette couleur doit être définie si et seulement si le numéro correspond bien à la page en cours de consultation.
Revenir dans le code de la page reponse.php,
Adapter le code PHP de la boucle for, comme suit :
...
}
$chaine.= "<div style='float:left; width:320px; margin-right:10px; font-size:12px; text-align:right;'>";
for($la_page=1; $la_page<=$nb_pages; $la_page++)
{
$couleur="";
if($la_page==$_POST["num_page"])
$couleur="color:#CC3300;";
$chaine.= "<div style='margin:5px; float:left; cursor:pointer; ".$couleur." ' onClick='document.getElementById(\"num_page\").value = \"".$la_page."\"; recolter();'>".$la_page."</div>";
}
$chaine.= "</div>";
print($chaine);
...
A chaque passage dans la boucle restituant les numéros, nous réinitialisons une variable que nous nommons
$couleur . Si la correspondance de page est effective (if($la_page==$_POST["num_page"])), nous réglons sa propriété Html sur un rouge rubis ($couleur="color:#CC3300;";). Puis, nous n'oublions pas de concaténer cet attribut dans la
propriété style du calque. En cas de non-correspondance, la variable est vide. De fait, cette concaténation n'affecte par les propriétés du calque contenant le numéro.
Enregistrer les modifications et basculer sur le navigateur Internet,
Recharger la page Web en validant sa barre d'adresse par le touche Entrée,
Choisir un département puis une ville à l'aide des deux listes déroulantes,
Cliquer sur les petits numéros pour naviguer au travers des pages,
Cette fois, l'indicateur de position renseigne sur la situation sans équivoque. Il s'agit d'une petite amélioration précieuse en termes d'ergonomie.
Nous avons donc bâti un
système de pagination réagissant parfaitement et dynamiquement en fonction des données extraites depuis la
base de données MySql . Dans une prochaine formation, nous verrons comment construire dynamiquement le contenu d'une seule page Web, en fonction de l'enregistrement cliqué, à des fins d'optimisation pour le développement.
Le
code Php complet pour ce
système de pagination est le suivant :
<?php
if(isset($_POST["choix_dep"]) && isset($_POST["choix_ville"]))
{
$liaison2 = mysqli_connect("127.0.0.1", "codePHP", "php123bd");
mysqli_select_db($liaison2,"ids");
$le_dep = $_POST["choix_dep"];
$la_ville = $_POST["choix_ville"];
$requete_nb = "SELECT COUNT(liste_num) AS NBP FROM liste_id WHERE liste_dep='".utf8_decode($le_dep)."' AND liste_ville='".utf8_decode($la_ville)."'";
$retours_nb = mysqli_query($liaison2,$requete_nb);
$tab_nb = mysqli_fetch_array($retours_nb);
$nb_pages=$tab_nb["NBP"];
$nb_pages = ceil($nb_pages/10);
$depart=1;
if(isset($_POST["num_page"]) && $_POST["num_page"]!="")
$depart = $_POST["num_page"];
$depart = ($depart-1)*10;
$requete = "SELECT liste_nom, liste_activite FROM liste_id WHERE liste_dep='".utf8_decode($le_dep)."' AND liste_ville='".utf8_decode($la_ville)."' ORDER BY liste_nom LIMIT ".$depart.",10;";
$retours = mysqli_query($liaison2,$requete);
$chaine = "";
while($retour = mysqli_fetch_array($retours))
{
$chaine .= "<div style='float:left; width:190px; margin-left:10px; font-size:12px; text-align:left;'>".utf8_encode(str_replace("#", "'", $retour["liste_nom"]))."</div><div style='float:left; width:130px; font-size:10px; text-align:left;'>".utf8_encode(str_replace("#", "'", $retour["liste_activite"]))."</div><br/>";
}
$chaine.= "<div style='float:left; width:320px; margin-right:10px; font-size:12px; text-align:right;'>";
for($la_page=1; $la_page<=$nb_pages; $la_page++)
{
$couleur="";
if($la_page==$_POST["num_page"])
$couleur="color:#CC3300;";
$chaine.= "<div style='margin:5px; float:left; cursor:pointer;".$couleur."' onClick='document.getElementById(\"num_page\").value = \"".$la_page."\"; recolter();'>".$la_page."</div>";
}
$chaine.= "</div>";
print($chaine);
mysqli_close($liaison2);
}
?>