neigedhiver
Messages postés2480Date d'inscriptionjeudi 30 novembre 2006StatutMembreDernière intervention14 janvier 201119 20 nov. 2007 à 18:01
kylekatarnls : "La sécurité de ma GET est à 100%, si ce n'est pas un int supérieur à 0, alors elle ne donne rien. De plus le "html perdu" et bien c'est les liens, je vais aps les coder en javascript."
Mouais, ben non... Mais séparer leur affichage du traitement, c'est pas réservé à une élite, c'est à la portée du premier venu et ça simplifie ENORMEMENT la tache du premier gus qui voudra modifier la mise en page. Parce que des liens construits sur plusieurs lignes à partir de morceaux de balises mélangés à des variables php avec des apostrophes, des guillemets échappés qu'on ne sait même plus lequel on doit fermer, excuse moi, mais c'est vraiment pas génial.
Y'a une fonciton toute bête de PHP qui permet de commencer à séparer l'affichage du traitement, c'est la base ; et cette fonction c'est sprintf, qui permet d'y voir quand même sacrément plus clair quand on balance une tripotée de variables dans une chaine.
Et puis tu parles d'une seconde pour 600 pages de 30 entrées... Moi je te parle aussi de charge mémoire et d'optimisation, d'une manière générale.
Essaie de voir un peu plus loin que le bout de ta souris... Quand on utilise une fonction de pagination pour mettre en page les résultats d'un moteur de recherche, ça peut être plusieurs utilisateurs, voire même plusieurs dizaines en même temps. 1 seconde de plus pour chaque personne, je te laisse imaginer la différence que ça fait pour le serveur. C'est pas négligeable. C'est même énorme.
Alors si tu dois charger les 15000 résultats d'une recherche dans une pauvre variable alors que tu vas n'en afficher que 30, je trouve déplorable un tel gâchis de RAM, alors qu'elle pourrait servir à autre chose (comme par exemple stocker plusieurs fois 30 résultats à afficher).
Maintenant si t'as pas du tout envie d'optimiser tes codes et préfères te contenter de piètres performances qui te suffisent, libre à toi. Si tu utilises tes codes pour un site perso avec maxi 3 utilisateurs simultanés, c'est un fait. Mais quand on publie une source, il est normal d'essayer d'optimiser le plus possible. Parce que sinon, la source ne sert à rien.
Maintenant, si tu lis un peu plus attentivement les remarques que j'ai soumises à Asherah et que tu compares sa réaction à la tienne, tu verras qu'il y a une différence.
Elle a reconnu que sa source n'était pas optimisée et elle se penche depuis sur une version orientée objet de sa source. Elle cherche à optimiser et n'a jamais prétendu que sa source était plus performante que la tienne.
Pfffffffffff
kylekatarnls
Messages postés35Date d'inscriptiondimanche 4 février 2007StatutMembreDernière intervention 1 juillet 2008 20 nov. 2007 à 17:43
La sécurité de ma GET est à 100%, si ce n'est pas un int supérieur à 0, alors elle ne donne rien. De plus le "html perdu" et bien c'est les liens, je vais aps les coder en javascript. Et je ne crois pas que tes 325 lignes non indentées et tes 12 zip soit plus aisés à décrypter.
Je t'ai dit ce que je pensais de ton code (que j'ai noté 5 et pas 0 quand même). Je n'ai présenté cette version que parce que tu me l'a demandé, elle a peut-être l'inconvéniant de prendre une seconde de plus lorsqu'on a 600 pages de 30 entrée BDD, tout comme elle a les avantages de prendre moins de place, de s'adpter à tous les contenus. Je prétends pas que ça vale mieux juste que je préfère utiliser ce code, et j'ai déjà expliqué pourquoi.
PS: Il serait judicieux de remplacer <<, <, >, >> dans les liens par < et > pour éviter des les erreurs de W3C.
neigedhiver
Messages postés2480Date d'inscriptionjeudi 30 novembre 2006StatutMembreDernière intervention14 janvier 201119 20 nov. 2007 à 00:28
J'aurais effectivement pu prendre 10 secondes pour lire le code...
if(count($array)>$nepp) //on ne pagine que si c'est nécessaire
C'est bien ce qui me semblait : on stocke dans le tableau TOUT ce qui doit être paginé, même si ça ne doit pas être affiché.
En plus, en faisant comme ça, ça implique une première lecture du résultat mysql, puis une seconde du tableau... Deux boucles sur les mêmes données pour ne les afficher qu'une seule fois... C'est dommage et un vrai gâchi de performances,alors qu'un itérateur permet de ne parcourir qu'une seule fois les données, et uniquement celles que l'on souhaite afficher... Franchement, moins de lignes, c'est un mauvais argument... En plus, pour parcourir un répertoire, là où il faut 10 lignes en procédural, il en faut 3 avec un itérateur (et je ne parle même pas de récursivité, où le nombre de lignes et la charge mémoire augmente de façon phénoménale en procédural, sans bouger augmenter exagérément avec un itérateur).
"$page=$_GET['souspage']*1;//Sous-page évite d'avoir tout à récoder si on utilise déjà une get page"
Mais ça oblige à tout recoder si on utiliser déjà $_GET['souspage']
Bref... Avec un peu de bonne volonté, on peut parvenir à faire du joli code performant... C'est pas difficile, et c'est pas non plus réservé à une élite.
cs_Asherah
Messages postés25Date d'inscriptionmercredi 14 novembre 2007StatutMembreDernière intervention25 novembre 2007 19 nov. 2007 à 21:52
Tu ne fait aucunes verifications sur tes transmissions de variable par get, j'aimerais pas l'avoir sur mon site.
Et c'est bete qu'il ne marche pas, car je suis sur que j'aurais pu trouver pleins de trucs du genre. si tu passe a la page 9 alors qu'il n y a que 6 pages tu retrouve dans le vide intersidérale de la bdd.
et puis beaucoup moins de lignes oui, mais sans possibilité de faire un pagination invérsée.
bref, j'aimerais que tu post cette source, voir ce que les autres en pense.
Ils y en a ici qui prennent du temp a faire des reponses constructive.
Et je les remercis beaucoup,et peut etre devrait tu prendre exemple sur eux.
Bon allé sur ce, je n'ajouterais rien, je viens ici pour partager et apprendre.
neigedhiver
Messages postés2480Date d'inscriptionjeudi 30 novembre 2006StatutMembreDernière intervention14 janvier 201119 19 nov. 2007 à 20:56
Salut,
@kylekatarnls : J'ai pas regardé ton code en détails, mais si on récupère ce qu'on veut paginer dans un array, excuse moi, mais niveau performances, c'est pas top... Inutile de récupérer TOUTES les données qui sont affichées sur plusieurs pages alors qu'on n'en affiche qu'une partie par page, et qu'on ne peut pas en afficher plus d'une page à chaque fois...
L'itérateur permet de n'itérer que sur une partie, sans surcharger le traitement et la mémoire. En plus, c'est plus joli et plus clair que plein de code avec du html perdu dedans et que personne n'a envie de chercher à décrypter...
kylekatarnls
Messages postés35Date d'inscriptiondimanche 4 février 2007StatutMembreDernière intervention 1 juillet 2008 19 nov. 2007 à 20:48
Alors la méthode que j'utilise en supposant que l'on est récupéré un contenu SQL ou un dossier dans un array ce qui je pense du coup peut s'adapter à tout :
<?php
$array= array(/*Le contenu à paginer*/);
$nepp=12;//Le nombre d'élément par page
$nbdp=7;//Le nomnbre de numéro de la pagination (impaire plus grand que 3)
if(count($array)>$nepp) //on ne pagine que si c'est nécessaire
{
$array=array_chunk($array,$nepp,true);
$pmax=count($array);
$page=$_GET['souspage']*1;//Sous-page évite d'avoir tout à récoder si on utilise déjà une get page
if(!isset($_GET['souspage']) || !is_int($page) || $page<1 || $page>$pmax)
$page=1;
$array=$array[$page-1];
// On a prélevé le contenu, maintenant on construit la barre des pages
$inter=' ';
if($pmax<=$nbdp)
{
for($i=1;$i<=$pmax;$i++)
if($i==$page)
$inter.='- '.$i.' - ';
else
$inter. ='[?souspage= '.$i.' ['.$i.']] ';
}
else
{
$coun=1;
for($i=min($pmax+1-$nbdp,max(1,ceil($page-(($nbdp-1)/2))));
$i<=min($pmax,max(7,ceil($page+(($nbdp-1)/2))));
$i++) {
if(($i!=1 && $coun==1) || ($i!=$pmax && $coun==$nbdp))
$inter.='... ';
elseif($i==$page)
$inter.='- '.$i.' - ';
else
$inter. ='[?souspage='.$i.' ['.$i.']] ';
$coun++;
}
$inter=' [?souspage='.max(1,$page-7).' <<] [?souspage='.max(1,$page-1).' <]'.$inter.'[?souspage='.min($pmax,$page+-1).' >] [?souspage='.min($pmax,$page+7).' >>] ';
}
}
echo $inter.'
'; // On affiche la pagination au dessus
foreach($array as $key=>$value)
{
//ici on exploite, par exemple on affiche :
echo $value['titre'].'
'.$value['message'].'<hr />';
}
echo $inter.'
'; // On affiche la pagination en dessous
?>
Voilà ça ne prend qu'une petite page c'est totalement paramètrable, qu'y a-t-il besoin de plus ?
cs_Asherah
Messages postés25Date d'inscriptionmercredi 14 novembre 2007StatutMembreDernière intervention25 novembre 2007 19 nov. 2007 à 17:05
merci^^
Ca va etre encore mieu lorsque j'aurais fait l'itérateur.^^ patience dans quelques jours ca va froler le codage extraterestre^^
hamidmx
Messages postés3Date d'inscriptionmercredi 7 novembre 2007StatutMembreDernière intervention18 juillet 2008 19 nov. 2007 à 15:41
c'est super, surtout après les modifs ...
malalam
Messages postés10839Date d'inscriptionlundi 24 février 2003StatutMembreDernière intervention 2 mars 201025 19 nov. 2007 à 13:20
Ouaip :-) On est bons ;-)
neigedhiver
Messages postés2480Date d'inscriptionjeudi 30 novembre 2006StatutMembreDernière intervention14 janvier 201119 19 nov. 2007 à 12:41
Asherah : "avec tout ca, je crois que je vais decouvrir une nouvelle dimension du php^^."
@malalam : Mission accomplie ^^
cs_Asherah
Messages postés25Date d'inscriptionmercredi 14 novembre 2007StatutMembreDernière intervention25 novembre 2007 19 nov. 2007 à 12:33
En tout cas elle à l'air genial ta source ^^,
Je vais m'en inspirer si je calle un peu, mais je vais quand meme essayer de faire mon propre itérateur, uniquement dans un but d'apprentissage (si je ne fait pas, je ne saurait pas^^), mais avec tout ca, je crois que je vais decouvrir une nouvelle dimension du php^^.
Merci beaucoup a tous^^.
malalam
Messages postés10839Date d'inscriptionlundi 24 février 2003StatutMembreDernière intervention 2 mars 201025 19 nov. 2007 à 08:23
cs_Asherah
Messages postés25Date d'inscriptionmercredi 14 novembre 2007StatutMembreDernière intervention25 novembre 2007 19 nov. 2007 à 01:14
Super!!
j'vais m'intérésser a tout ca, et je vais essayer de l'adapter a la pagination.^^
merci beaucoup^^
neigedhiver
Messages postés2480Date d'inscriptionjeudi 30 novembre 2006StatutMembreDernière intervention14 janvier 201119 19 nov. 2007 à 01:11
Ouaip, pardon...
Euh donc je disais ça par spécifiquement pour toi, mais pour ta source. Je donne une piste d'optimisation.
Un itérateur, c'est un objet (instance d'une classe) qui a certaines méthodes (fonctions) définies pour réagir aux fonctions php suivantes :
- current()
- next()
- valid()
- rewind()
- key()
Typiquement, un itérateur est utilisé dans une boucle foreach. La boucle foreach est particulièrement pratique puisqu'elle exécute toute seule ces fonctions sur la variable qui est passée en paramètre.
Lors de l'exécution de cette boucle :
foreach ($aTableau as $sLigne) {
echo $sLigne;
}
foreach effectue tout seul les instructions suivantes :
Initialisation de la boucle :
- rewind($aTableau)
- valid($aTableau)
Une boucle (1 élément) :
- current($aTableau)
- key($aTableau)
- next($aTableau)
- valid($aTableau)
A la fin d'une boucle, si valid() renvoie TRUE, une nouvelle boucle est faite. Sinon, foreach s'arrête.
Un itérateur permet donc de contrôler comment on parcourt quelque chose (un objet, un tableau, n'importe quoi).
Le parcours d'un répertoire peut se faire en 3 lignes. Le parcours récursif d'un répertoire (le répertoire ainsi que tous ses sous-répertoires) idem.
En sacrifiant une ligne supplémentaire de code on peut filtrer les répertoires que l'on affiche (ne pas afficher "." et "..", ne pas afficher les fichiers cachés, ou uniquement ceux qui se terminent par ".truc.php").
Concrètement, pour ton cas, un itérateur permettrait de ne parcourir que quelques enregistrements du résultat d'une requête SQL, ou que quelques fichiers d'un répertoire, etc.
Quelques classes permettraient de spécialiser certaines tâches, comme la récupération de ce qu'il faut paginer, et l'affichage de ce quelque chose à paginer. Cela permet d'avoir autant de classes qu'on le souhaite, pour paginer un résultat de requete, des fichiers, le contenu d'un tableau, etc. Sans avoir jamais à modifier le code de l'affichage de la page.
Enfin voilà... Je sais pas si c'était vraiment le meilleur endroit pour tout ça, mais bon...
Si t'y vois pas plus clair, n'hésite pas à poser des questions. J'aime bien les gens curieux, l'étant moi-même : c'est comme ça qu'on progresse.
cs_Asherah
Messages postés25Date d'inscriptionmercredi 14 novembre 2007StatutMembreDernière intervention25 novembre 2007 19 nov. 2007 à 00:45
^^
c'est quoi un itérateur? Oo
excuse moi, mais la je suis un peu dans le brouillard.
Et puis tu parle pour moi si je veut faire une pagination?
parceque la, je propose un pagination pour les autres,
et surtout pour les tonnes de petit noobs comme moi qui savent pas ce que c'est un itérateur. +_O
Mais par contre je suis curieuse de savoir, alors si t avais la meme chose en francais.
(oui,j ai pas eu le temp d'apprendre l'anglais a l'ecole :/)
chui preneuse^^
neigedhiver
Messages postés2480Date d'inscriptionjeudi 30 novembre 2006StatutMembreDernière intervention14 janvier 201119 18 nov. 2007 à 23:29
Non mais si tu veux vraiment optimiser comme ça, le mieux, c'est encore d'utiliser des itérateurs.
Pour le coup, tu gagnerais non seulement en nombre de lignes, mais aussi en performances, en lisibilité et en facilité de maintenance...
Un peu de lecture : http://www.php.net/~helly/php/ext/spl/
^^
cs_Asherah
Messages postés25Date d'inscriptionmercredi 14 novembre 2007StatutMembreDernière intervention25 novembre 2007 18 nov. 2007 à 23:27
Mais je vais rajouter l'option demain.
Je metterais aussi comme pour la pagination bdd les formats invérsé ou non et no_fonction .
cs_Asherah
Messages postés25Date d'inscriptionmercredi 14 novembre 2007StatutMembreDernière intervention25 novembre 2007 18 nov. 2007 à 23:22
il ne faut pas enlever la fonction en haut non plus.
cs_Asherah
Messages postés25Date d'inscriptionmercredi 14 novembre 2007StatutMembreDernière intervention25 novembre 2007 18 nov. 2007 à 23:13
erff il ne faut pas enlever le "# $total = count($tableau); "
je corrige:
"# function pagination($conteneur_bd_debut, $conteneur_bd_fin, $conteneur_pg_debut, $conteneur_pg_fin, $page, $nbr_par_page, $nbr_liens, $inverse, $champ, $table, $where, $active, $limite_debut, $limite_fin){
# if($active == 'oui'){
# $sql = "SELECT $champ FROM $table WHERE $where BETWEEN $limite_debut AND $limite_fin";
# }
# else{
# $sql = "SELECT $champ FROM $table ORDER BY $where";
# }
# $req = mysql_query($sql) or die('Erreur SQL !
'.$sql.'
'.mysql_error());
# while($data1 = mysql_fetch_assoc($req))
# {
# $tableau[] = $data1[$champ];
# }
# $total = count($tableau); "
-------------------------------------------------------
par:
-------------------------------------------------------
$dossier = 'ton_dossier';
$tableau = array();
if(is_dir($dossier)) {
$dir = opendir($dossier) or die('Impossible d\'ouvrir le dossier');
while (false !($file readdir($dir))) {
if ($file != '.' && $file != '..') {
$tableau[] = $file;
}
}
}
-----------------------------------------------------------
et tu pagine un dossier.
Maintenant si tu a fait plus complexe en beaucoup moins de ligne, je veut bien voir^^.
Et si tu pouvais developpé un peu plus, aussi je suis preneuse.
kylekatarnls
Messages postés35Date d'inscriptiondimanche 4 février 2007StatutMembreDernière intervention 1 juillet 2008 18 nov. 2007 à 22:33
Je trouve le code un peu long et lourd pour une simple pagination, j'ai déjà fait des paginations plus complexes qui prennent beaucoup moins de lignes de code, de plus toute pagination n'est pas liée à une BDD.
L'idée est bonne mais je pense qu'on peut faire mieux.
cs_Asherah
Messages postés25Date d'inscriptionmercredi 14 novembre 2007StatutMembreDernière intervention25 novembre 2007 18 nov. 2007 à 21:10
Salut^^
merci pour tes commentaires.
en fait a la base je n'ai pas fait ce script pour etre une fonction en soit, c'est pour cela qu'il y a en effet beaucoups de parametres, mais je n'ai pas voulus en postant cette source ici qu'elle se limite aux initiés du php, mais je voulais quelle soit accessible meme aux plus novices...
J'ai mis un zip "no_fonction" qui justement, permet de l'exploiter sans ces parametres...
sinon, pour ce qui est du between, tu as raison je vais optimisé la chose ^^.
merci encore^^
neigedhiver
Messages postés2480Date d'inscriptionjeudi 30 novembre 2006StatutMembreDernière intervention14 janvier 201119 18 nov. 2007 à 19:23
Salut,
J'ai du mal à comprendre l'intérêt de spécifier en argument les limites inférieure et supérieure des enregistrements à retourner, si ensuite le script recalcule le nombre de pages...
Il m'aurait semble plus rationnel de laisser le script calculer les limites inf. et sup. en fonction de la page demandée et du nombre de pages.
En fait, utiliser BETWEEN pour une pagination n'a de sens que si aucun enregistrement n'a été supprimé.
Si ta table comprends 20 engistrements, que le premier a été supprimé et un autre au milieu, alors les index ont des valeurs allant de 2 à 21. Et pas de 1 à 20. Du coup, le 5ème enregistrement, par exemple, porte l'index 6.
Il faut un autre index, différent de la clé primaire, que tu gères toi-même dans ton script, pour t'assurer qu'aucun ne manque.
Ainsi, lorsque l'on supprime l'enregistrement 5, on décrémente tous les suivants de 1, pour qu'il n'y ait pas de trou. On peut alors utiliser BETWEEN en toute sérénité.
Autre optimisation : tu parcours le résultat et stockes tous les enregistrements dans un tableau associatif, quitte à n'en utiliser qu'une partie ensuite. C'est un peu lourd.
Le plus malin serait de se positionner directement sur le premier enregistrement que l'on souhaite avec mysql_data_seek(), et de boucler autant de fois qu'on veut d'enregistrements. On évite d'avoir un tableau avec plein de trucs inutiles.
Le plus rusé, encore, serait de savoir à l'avance combien d'enregistrements il y a dans la table. Un simple SELECT COUNT(id) FROM table; le dit. Puisqu'on compte un nombre de clés primaires, la requête ne prend pas beaucoup de ressources : mysql est optimisé pour ce genre de requête.
On peut alors tranquillement calculer les premier et dernier enregistrements que l'on souhaite récupérer. La requête ne retournera alors que des enregistrements qui seront utilisés. On n'a alors plus besoin de boucler 2 fois sur le tableau (1 remplissage, 1 lecture). On boucle directement sur le résultat, directement en lecture pour l'afficher.
Trois petites choses encore :
- je déplore que ta fonction demande autant de paramètres
- dommage qu'il n'y ait pas plus de commentaires, parce qu'on a du mal à savoir à quoi sert chaque ligne
- il est fort regrettable que l'affichage html et le traitement des données soient mélangés... On s'y perd, et pour personnaliser le code HTML de sortie, c'est pas évident.
cs_Asherah
Messages postés25Date d'inscriptionmercredi 14 novembre 2007StatutMembreDernière intervention25 novembre 2007 18 nov. 2007 à 18:38
Voili! un gros update!
-possibilité d'avoir la pagination invérsée.
-possibilité de restreindre la recherche SQL grace a BETWEEN.
La source est maintenant livrée avec 4 zip.
A savoir la source de base facilement configurable depuis l'index avec la gestion invérsée ou pas pour les novices.
Les versions "allégées" uniquement invérsée ou normal.
Et les version sans l'index, a configurer depuis le script lui meme, pour ceux a qui ca ne fait pas peur. ^^
Voili, et bon paginage^^
cs_Asherah
Messages postés25Date d'inscriptionmercredi 14 novembre 2007StatutMembreDernière intervention25 novembre 2007 17 nov. 2007 à 17:10
La présentation graphique est dépouillée a son maximum,
uniquement pour que vous puissiez facilement l'intégrer a votre site avec une mise en forme CSS ou autre.
N'hésitez pas à laisser vos commentaires et pourquoi pas mettre une note^^.
20 nov. 2007 à 18:01
Mouais, ben non... Mais séparer leur affichage du traitement, c'est pas réservé à une élite, c'est à la portée du premier venu et ça simplifie ENORMEMENT la tache du premier gus qui voudra modifier la mise en page. Parce que des liens construits sur plusieurs lignes à partir de morceaux de balises mélangés à des variables php avec des apostrophes, des guillemets échappés qu'on ne sait même plus lequel on doit fermer, excuse moi, mais c'est vraiment pas génial.
Y'a une fonciton toute bête de PHP qui permet de commencer à séparer l'affichage du traitement, c'est la base ; et cette fonction c'est sprintf, qui permet d'y voir quand même sacrément plus clair quand on balance une tripotée de variables dans une chaine.
Et puis tu parles d'une seconde pour 600 pages de 30 entrées... Moi je te parle aussi de charge mémoire et d'optimisation, d'une manière générale.
Essaie de voir un peu plus loin que le bout de ta souris... Quand on utilise une fonction de pagination pour mettre en page les résultats d'un moteur de recherche, ça peut être plusieurs utilisateurs, voire même plusieurs dizaines en même temps. 1 seconde de plus pour chaque personne, je te laisse imaginer la différence que ça fait pour le serveur. C'est pas négligeable. C'est même énorme.
Alors si tu dois charger les 15000 résultats d'une recherche dans une pauvre variable alors que tu vas n'en afficher que 30, je trouve déplorable un tel gâchis de RAM, alors qu'elle pourrait servir à autre chose (comme par exemple stocker plusieurs fois 30 résultats à afficher).
Maintenant si t'as pas du tout envie d'optimiser tes codes et préfères te contenter de piètres performances qui te suffisent, libre à toi. Si tu utilises tes codes pour un site perso avec maxi 3 utilisateurs simultanés, c'est un fait. Mais quand on publie une source, il est normal d'essayer d'optimiser le plus possible. Parce que sinon, la source ne sert à rien.
Maintenant, si tu lis un peu plus attentivement les remarques que j'ai soumises à Asherah et que tu compares sa réaction à la tienne, tu verras qu'il y a une différence.
Elle a reconnu que sa source n'était pas optimisée et elle se penche depuis sur une version orientée objet de sa source. Elle cherche à optimiser et n'a jamais prétendu que sa source était plus performante que la tienne.
Pfffffffffff
20 nov. 2007 à 17:43
Je t'ai dit ce que je pensais de ton code (que j'ai noté 5 et pas 0 quand même). Je n'ai présenté cette version que parce que tu me l'a demandé, elle a peut-être l'inconvéniant de prendre une seconde de plus lorsqu'on a 600 pages de 30 entrée BDD, tout comme elle a les avantages de prendre moins de place, de s'adpter à tous les contenus. Je prétends pas que ça vale mieux juste que je préfère utiliser ce code, et j'ai déjà expliqué pourquoi.
PS: Il serait judicieux de remplacer <<, <, >, >> dans les liens par < et > pour éviter des les erreurs de W3C.
20 nov. 2007 à 00:28
if(count($array)>$nepp) //on ne pagine que si c'est nécessaire
C'est bien ce qui me semblait : on stocke dans le tableau TOUT ce qui doit être paginé, même si ça ne doit pas être affiché.
En plus, en faisant comme ça, ça implique une première lecture du résultat mysql, puis une seconde du tableau... Deux boucles sur les mêmes données pour ne les afficher qu'une seule fois... C'est dommage et un vrai gâchi de performances,alors qu'un itérateur permet de ne parcourir qu'une seule fois les données, et uniquement celles que l'on souhaite afficher... Franchement, moins de lignes, c'est un mauvais argument... En plus, pour parcourir un répertoire, là où il faut 10 lignes en procédural, il en faut 3 avec un itérateur (et je ne parle même pas de récursivité, où le nombre de lignes et la charge mémoire augmente de façon phénoménale en procédural, sans bouger augmenter exagérément avec un itérateur).
"$page=$_GET['souspage']*1;//Sous-page évite d'avoir tout à récoder si on utilise déjà une get page"
Mais ça oblige à tout recoder si on utiliser déjà $_GET['souspage']
Bref... Avec un peu de bonne volonté, on peut parvenir à faire du joli code performant... C'est pas difficile, et c'est pas non plus réservé à une élite.
19 nov. 2007 à 21:52
Et c'est bete qu'il ne marche pas, car je suis sur que j'aurais pu trouver pleins de trucs du genre. si tu passe a la page 9 alors qu'il n y a que 6 pages tu retrouve dans le vide intersidérale de la bdd.
et puis beaucoup moins de lignes oui, mais sans possibilité de faire un pagination invérsée.
bref, j'aimerais que tu post cette source, voir ce que les autres en pense.
Ils y en a ici qui prennent du temp a faire des reponses constructive.
Et je les remercis beaucoup,et peut etre devrait tu prendre exemple sur eux.
Bon allé sur ce, je n'ajouterais rien, je viens ici pour partager et apprendre.
19 nov. 2007 à 20:56
@kylekatarnls : J'ai pas regardé ton code en détails, mais si on récupère ce qu'on veut paginer dans un array, excuse moi, mais niveau performances, c'est pas top... Inutile de récupérer TOUTES les données qui sont affichées sur plusieurs pages alors qu'on n'en affiche qu'une partie par page, et qu'on ne peut pas en afficher plus d'une page à chaque fois...
L'itérateur permet de n'itérer que sur une partie, sans surcharger le traitement et la mémoire. En plus, c'est plus joli et plus clair que plein de code avec du html perdu dedans et que personne n'a envie de chercher à décrypter...
19 nov. 2007 à 20:48
<?php
$array= array(/*Le contenu à paginer*/);
$nepp=12;//Le nombre d'élément par page
$nbdp=7;//Le nomnbre de numéro de la pagination (impaire plus grand que 3)
if(count($array)>$nepp) //on ne pagine que si c'est nécessaire
{
$array=array_chunk($array,$nepp,true);
$pmax=count($array);
$page=$_GET['souspage']*1;//Sous-page évite d'avoir tout à récoder si on utilise déjà une get page
if(!isset($_GET['souspage']) || !is_int($page) || $page<1 || $page>$pmax)
$page=1;
$array=$array[$page-1];
// On a prélevé le contenu, maintenant on construit la barre des pages
$inter=' ';
if($pmax<=$nbdp)
{
for($i=1;$i<=$pmax;$i++)
if($i==$page)
$inter.='- '.$i.' - ';
else
$inter. ='[?souspage= '.$i.' ['.$i.']] ';
}
else
{
$coun=1;
for($i=min($pmax+1-$nbdp,max(1,ceil($page-(($nbdp-1)/2))));
$i<=min($pmax,max(7,ceil($page+(($nbdp-1)/2))));
$i++) {
if(($i!=1 && $coun==1) || ($i!=$pmax && $coun==$nbdp))
$inter.='... ';
elseif($i==$page)
$inter.='- '.$i.' - ';
else
$inter. ='[?souspage='.$i.' ['.$i.']] ';
$coun++;
}
$inter=' [?souspage='.max(1,$page-7).' <<] [?souspage='.max(1,$page-1).' <]'.$inter.'[?souspage='.min($pmax,$page+-1).' >] [?souspage='.min($pmax,$page+7).' >>] ';
}
}
echo $inter.'
'; // On affiche la pagination au dessus
foreach($array as $key=>$value)
{
//ici on exploite, par exemple on affiche :
echo $value['titre'].'
'.$value['message'].'<hr />';
}
echo $inter.'
'; // On affiche la pagination en dessous
?>
Voilà ça ne prend qu'une petite page c'est totalement paramètrable, qu'y a-t-il besoin de plus ?
19 nov. 2007 à 17:05
Ca va etre encore mieu lorsque j'aurais fait l'itérateur.^^ patience dans quelques jours ca va froler le codage extraterestre^^
19 nov. 2007 à 15:41
19 nov. 2007 à 13:20
19 nov. 2007 à 12:41
@malalam : Mission accomplie ^^
19 nov. 2007 à 12:33
Je vais m'en inspirer si je calle un peu, mais je vais quand meme essayer de faire mon propre itérateur, uniquement dans un but d'apprentissage (si je ne fait pas, je ne saurait pas^^), mais avec tout ca, je crois que je vais decouvrir une nouvelle dimension du php^^.
Merci beaucoup a tous^^.
19 nov. 2007 à 08:23
Ca peut te servir de base :
http://www.phpcs.com/codes/PHP5-LIMIT-PACKAGE-LIMITATION-GENERIQUE-JEU-RESULTAT-ITERATEURS_40545.aspx
19 nov. 2007 à 01:14
j'vais m'intérésser a tout ca, et je vais essayer de l'adapter a la pagination.^^
merci beaucoup^^
19 nov. 2007 à 01:11
Euh donc je disais ça par spécifiquement pour toi, mais pour ta source. Je donne une piste d'optimisation.
Un itérateur, c'est un objet (instance d'une classe) qui a certaines méthodes (fonctions) définies pour réagir aux fonctions php suivantes :
- current()
- next()
- valid()
- rewind()
- key()
Typiquement, un itérateur est utilisé dans une boucle foreach. La boucle foreach est particulièrement pratique puisqu'elle exécute toute seule ces fonctions sur la variable qui est passée en paramètre.
Lors de l'exécution de cette boucle :
foreach ($aTableau as $sLigne) {
echo $sLigne;
}
foreach effectue tout seul les instructions suivantes :
Initialisation de la boucle :
- rewind($aTableau)
- valid($aTableau)
Une boucle (1 élément) :
- current($aTableau)
- key($aTableau)
- next($aTableau)
- valid($aTableau)
A la fin d'une boucle, si valid() renvoie TRUE, une nouvelle boucle est faite. Sinon, foreach s'arrête.
Un itérateur permet donc de contrôler comment on parcourt quelque chose (un objet, un tableau, n'importe quoi).
Le parcours d'un répertoire peut se faire en 3 lignes. Le parcours récursif d'un répertoire (le répertoire ainsi que tous ses sous-répertoires) idem.
En sacrifiant une ligne supplémentaire de code on peut filtrer les répertoires que l'on affiche (ne pas afficher "." et "..", ne pas afficher les fichiers cachés, ou uniquement ceux qui se terminent par ".truc.php").
Bon là, je commence à rentrer dans le tuto... Alors qu'il en existe déjà : http://www.phpcs.com/tutoriaux/UTILISER-ITERATEURS-PHP5_640.aspx
Concrètement, pour ton cas, un itérateur permettrait de ne parcourir que quelques enregistrements du résultat d'une requête SQL, ou que quelques fichiers d'un répertoire, etc.
Quelques classes permettraient de spécialiser certaines tâches, comme la récupération de ce qu'il faut paginer, et l'affichage de ce quelque chose à paginer. Cela permet d'avoir autant de classes qu'on le souhaite, pour paginer un résultat de requete, des fichiers, le contenu d'un tableau, etc. Sans avoir jamais à modifier le code de l'affichage de la page.
Enfin voilà... Je sais pas si c'était vraiment le meilleur endroit pour tout ça, mais bon...
Si t'y vois pas plus clair, n'hésite pas à poser des questions. J'aime bien les gens curieux, l'étant moi-même : c'est comme ça qu'on progresse.
19 nov. 2007 à 00:45
c'est quoi un itérateur? Oo
excuse moi, mais la je suis un peu dans le brouillard.
Et puis tu parle pour moi si je veut faire une pagination?
parceque la, je propose un pagination pour les autres,
et surtout pour les tonnes de petit noobs comme moi qui savent pas ce que c'est un itérateur. +_O
Mais par contre je suis curieuse de savoir, alors si t avais la meme chose en francais.
(oui,j ai pas eu le temp d'apprendre l'anglais a l'ecole :/)
chui preneuse^^
18 nov. 2007 à 23:29
Pour le coup, tu gagnerais non seulement en nombre de lignes, mais aussi en performances, en lisibilité et en facilité de maintenance...
Un peu de lecture : http://www.php.net/~helly/php/ext/spl/
^^
18 nov. 2007 à 23:27
Je metterais aussi comme pour la pagination bdd les formats invérsé ou non et no_fonction .
18 nov. 2007 à 23:22
18 nov. 2007 à 23:13
je corrige:
"------------------fonction_pagination.php----------------------
"# function pagination($conteneur_bd_debut, $conteneur_bd_fin, $conteneur_pg_debut, $conteneur_pg_fin, $page, $nbr_par_page, $nbr_liens, $inverse, $champ, $table, $where, $active, $limite_debut, $limite_fin){
# if($active == 'oui'){
# $sql = "SELECT $champ FROM $table WHERE $where BETWEEN $limite_debut AND $limite_fin";
# }
# else{
# $sql = "SELECT $champ FROM $table ORDER BY $where";
# }
# $req = mysql_query($sql) or die('Erreur SQL !
'.$sql.'
'.mysql_error());
# while($data1 = mysql_fetch_assoc($req))
# {
# $tableau[] = $data1[$champ];
# }
--------------------------------------------------------
par:
-------------------------------------------------------
$dossier = 'ton_dossier';
$tableau = array();
if(is_dir($dossier)) {
$dir = opendir($dossier) or die('Impossible d\'ouvrir le dossier');
while (false !($file readdir($dir))) {
if ($file != '.' && $file != '..') {
$tableau[] = $file;
}
}
}
-----------------------------------------------------------
18 nov. 2007 à 23:09
Sache que ma pagination n'est pas faite uniquement pour la BDD, elle est aussi concue pour lire et paginé un dossier tu a juste a remplacé
------------------fonction_pagination.php----------------------
"# function pagination($conteneur_bd_debut, $conteneur_bd_fin, $conteneur_pg_debut, $conteneur_pg_fin, $page, $nbr_par_page, $nbr_liens, $inverse, $champ, $table, $where, $active, $limite_debut, $limite_fin){
# if($active == 'oui'){
# $sql = "SELECT $champ FROM $table WHERE $where BETWEEN $limite_debut AND $limite_fin";
# }
# else{
# $sql = "SELECT $champ FROM $table ORDER BY $where";
# }
# $req = mysql_query($sql) or die('Erreur SQL !
'.$sql.'
'.mysql_error());
# while($data1 = mysql_fetch_assoc($req))
# {
# $tableau[] = $data1[$champ];
# }
# $total = count($tableau); "
-------------------------------------------------------
par:
-------------------------------------------------------
$dossier = 'ton_dossier';
$tableau = array();
if(is_dir($dossier)) {
$dir = opendir($dossier) or die('Impossible d\'ouvrir le dossier');
while (false !($file readdir($dir))) {
if ($file != '.' && $file != '..') {
$tableau[] = $file;
}
}
}
-----------------------------------------------------------
et tu pagine un dossier.
Maintenant si tu a fait plus complexe en beaucoup moins de ligne, je veut bien voir^^.
Et si tu pouvais developpé un peu plus, aussi je suis preneuse.
18 nov. 2007 à 22:33
L'idée est bonne mais je pense qu'on peut faire mieux.
18 nov. 2007 à 21:10
merci pour tes commentaires.
en fait a la base je n'ai pas fait ce script pour etre une fonction en soit, c'est pour cela qu'il y a en effet beaucoups de parametres, mais je n'ai pas voulus en postant cette source ici qu'elle se limite aux initiés du php, mais je voulais quelle soit accessible meme aux plus novices...
J'ai mis un zip "no_fonction" qui justement, permet de l'exploiter sans ces parametres...
sinon, pour ce qui est du between, tu as raison je vais optimisé la chose ^^.
merci encore^^
18 nov. 2007 à 19:23
J'ai du mal à comprendre l'intérêt de spécifier en argument les limites inférieure et supérieure des enregistrements à retourner, si ensuite le script recalcule le nombre de pages...
Il m'aurait semble plus rationnel de laisser le script calculer les limites inf. et sup. en fonction de la page demandée et du nombre de pages.
En fait, utiliser BETWEEN pour une pagination n'a de sens que si aucun enregistrement n'a été supprimé.
Si ta table comprends 20 engistrements, que le premier a été supprimé et un autre au milieu, alors les index ont des valeurs allant de 2 à 21. Et pas de 1 à 20. Du coup, le 5ème enregistrement, par exemple, porte l'index 6.
Il faut un autre index, différent de la clé primaire, que tu gères toi-même dans ton script, pour t'assurer qu'aucun ne manque.
Ainsi, lorsque l'on supprime l'enregistrement 5, on décrémente tous les suivants de 1, pour qu'il n'y ait pas de trou. On peut alors utiliser BETWEEN en toute sérénité.
Autre optimisation : tu parcours le résultat et stockes tous les enregistrements dans un tableau associatif, quitte à n'en utiliser qu'une partie ensuite. C'est un peu lourd.
Le plus malin serait de se positionner directement sur le premier enregistrement que l'on souhaite avec mysql_data_seek(), et de boucler autant de fois qu'on veut d'enregistrements. On évite d'avoir un tableau avec plein de trucs inutiles.
Le plus rusé, encore, serait de savoir à l'avance combien d'enregistrements il y a dans la table. Un simple SELECT COUNT(id) FROM table; le dit. Puisqu'on compte un nombre de clés primaires, la requête ne prend pas beaucoup de ressources : mysql est optimisé pour ce genre de requête.
On peut alors tranquillement calculer les premier et dernier enregistrements que l'on souhaite récupérer. La requête ne retournera alors que des enregistrements qui seront utilisés. On n'a alors plus besoin de boucler 2 fois sur le tableau (1 remplissage, 1 lecture). On boucle directement sur le résultat, directement en lecture pour l'afficher.
Trois petites choses encore :
- je déplore que ta fonction demande autant de paramètres
- dommage qu'il n'y ait pas plus de commentaires, parce qu'on a du mal à savoir à quoi sert chaque ligne
- il est fort regrettable que l'affichage html et le traitement des données soient mélangés... On s'y perd, et pour personnaliser le code HTML de sortie, c'est pas évident.
18 nov. 2007 à 18:38
-possibilité d'avoir la pagination invérsée.
-possibilité de restreindre la recherche SQL grace a BETWEEN.
La source est maintenant livrée avec 4 zip.
A savoir la source de base facilement configurable depuis l'index avec la gestion invérsée ou pas pour les novices.
Les versions "allégées" uniquement invérsée ou normal.
Et les version sans l'index, a configurer depuis le script lui meme, pour ceux a qui ca ne fait pas peur. ^^
Voili, et bon paginage^^
17 nov. 2007 à 17:10
uniquement pour que vous puissiez facilement l'intégrer a votre site avec une mise en forme CSS ou autre.
N'hésitez pas à laisser vos commentaires et pourquoi pas mettre une note^^.