Pagination : page vide en cliquant sur le lien

Eléphanteau du PHP | 11 Messages

07 juil. 2012, 14:21

Bonjour,

J'ai un problème que je n'arrive pas à résoudre dans le bout de code permettant de limiter la pagination du nombre de livres par auteur.

Avant de cliquer sur les liens de pagination, lorsque j'affiche un auteur par la méthode GET, j'obtiens un page avec l'auteur en question, avec une url de type ".php?id=", où id correspond au nom de l'auteur, ainsi que la liste de livres, limitée par la fonction LIMIT de ma requête SQL, et obtenu par la jointure de mes bases sur cette même requête. Jusque là tout va bien ou presque.

Mon problème survient lorsque je veux passer aux ouvrages suivant via les liens de pagination.

En cliquant sur le lien, j'obtiens bien une url de type (.php?page=2) censée reprendre l'affichage des livres suivants, mais cette page n'affiche nie les données de l'auteur en question ni la suite de la liste des livres obtenu lors de l'affichage de ma première requête de l'auteur de méthode GET ".php?id=".

Merci pour votre aide.
<?php
include_once('connections/connect.inc.php') ;

class Pager{

public static function getPagerData($num_pages, $limit, $page){
   
    $num_pages = ceil($num_pages / $limit);
    $page = max($page, 1);
    $page = min($page, $num_pages);
    
    $offset = ($page - 1) * $limit;
    
    $ret = new stdClass;

    $ret->offset   = $offset;
    $ret->limit    = $limit;
    $ret->num_pages = $num_pages;
    $ret->page     = $page;
  
    return $ret;
}
}

$page_name = htmlentities($_SERVER['PHP_SELF']);
$limit = 2;
if(!isset($_data))
 {
    try
    {
		$bdd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $query = "
		SELECT 
		count(livres.id)
		AS total 
		FROM livres 
		INNER JOIN auteurs 
		ON auteurs.id = livres.auteur_id
		WHERE auteurs.id = livres.id";	
				
        $req = $bdd->prepare($query);
		try {
        	$req->execute();
        	}
       catch(PDOException $e) {
       		die('Erreur MySQL : ' . $e->errorInfo[2]);
        	}
        $data = $req->fetch(PDO::FETCH_COLUMN);
		    }
    catch (Exception $e)
    {
        $data = 0;
    }
 }

   
    if( filter_has_var(INPUT_GET, "page") == false)
    {
        $page = 1;
    } 
    elseif(filter_var($_GET['page'], FILTER_VALIDATE_INT, array("min_range"=>1, "max_range"=>$data)) == false)
     {
        $page = 1;
    }
    else
    {	
        $page = (int)$_GET['page'];		
    }        

 if($data == 0)
 {
    $content = 'Il n\'y a pas de données.';
 }
 else
 {   
    $pager = Pager::getPagerData($data, $limit, $page);
   
    $offset = $pager->offset;
    $limit  = $pager->limit;
    $page   = $pager->page;
	    
    $menu = '';    
   
    if($page != 1)
    {
        $menu .= '<li><a href="'.$page_name.'?page='.($page - 1).'"><< PREV </a></li>';
    }
   
    for ($i = 1; $i <= $pager->num_pages; $i++)
    {
        if ($i == $pager->page)
        {
            $menu .= '<li class="selected">'.$i.'</li>';
        }
        else
        {
            $menu .= '<li><a href="'.$page_name.'?page='.$i.'">'.$i.'</a></li>'."\n";
        }
    }
   
    if ($page < $pager->num_pages)  
    {
        $menu .= '<li><a href="'.$page_name.'?page='.($page + 1).'"> NEXT >></a></li>';
    }

$bdd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$query = <<<EOQ
SELECT
livres.id,	
livres.titre,
livres.sous_titre,
livres.lien_img,
livres.parution,
livres.resume,
livres.prix,		
auteurs.prenom_nom AS auteur_nom,
auteurs.id AS auteur_id,
auteurs.lien_img AS auteur_img,
auteurs.biographie
FROM livres
INNER JOIN 	auteurs
ON	auteurs.id = livres.auteur_id
WHERE auteurs.id = :id
LIMIT :limit
OFFSET :offset
EOQ;
$req = $bdd->prepare($query);
$req->bindParam(':limit', $limit, PDO::PARAM_INT);
$req->bindParam(':offset', $offset, PDO::PARAM_INT);
$req->bindValue(':id', (int)$_GET['id'], PDO::PARAM_INT);
try {
   $req->execute();
}
catch(PDOException $e) {
   die('Erreur MySQL : ' . $e->errorInfo[2]);
}
	
$res = $req->fetchAll(PDO::FETCH_ASSOC);
$content = '';
    foreach ($res as $row)
    {
        $content .= '
        <article id="content2">
        	        <img src="img/cover_img/'.$row['lien_img'].'.png" alt="" id="cover">   
        	        <h2 class="titre"><a href="livre_numerique.php?id='.$row['id'].'">'.$row['titre'].'</a></h2>
        	        <h3 class="titre">'.$row['sous_titre'].'</h3>
        	        <p>Paru le : '.$row['parution'].'
       	          </p>
        	        <p>Description : '.$row['resume'].'</p>
        	        <p class="prix">À partir de : '.$row['prix'].' €</p>
        	    </article>';
	}	
 }
?>

ViPHP
ViPHP | 2577 Messages

07 juil. 2012, 19:27

Bonjour,

Je te conseille d'afficher la requête qui permet d'extraire les lignes pour voir si elle correspond bien à ce que tu attends.
Tu pourras ensuite afficher les résultats intermédiaires pour voir ou le calcul foire (si c'est le cas).

A priori, pour limit, c'est 1 pour la page 1 (à vérifier)

Eléphanteau du PHP | 11 Messages

07 juil. 2012, 19:44

merci pour ta réponse.
la variable $limit= 2 permet de limiter le nombre de livres par auteur à afficher dans ma page, en l'occurrence 2. (LIMIT:limit =(LIMIT = $limit)
Pour la première requête SQL permettant de compter le nombre de livres total par auteur, j'ai vérifié le résultat, c'est bien ce que je veux.

Par contre, il y a un petit bug sur la page du forum. Pour la deuxième requête j'ai bien le paramètre de la syntaxe HEREDOC "OFFSET:offset " au lieu du code PHP retranscrit !!!

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

07 juil. 2012, 20:37

Je n'ai pas regardé ton code en détail, mais à première vue, si pour charger ta liste sur la première page tu as besoin de passer le paramètre id, il y a de fortes chances que tu en ais également besoin sur ta seconde page pour afficher les résultats suivants.

En gros, ton lien vers la page 2 devrait être du genre .php?id=XXX&page=2 et non pas juste .php?page=2
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

ViPHP
ViPHP | 2577 Messages

07 juil. 2012, 20:45

j'ai également un doute sur WHERE auteurs.id = livres.id"; pour le count

Eléphanteau du PHP | 11 Messages

08 juil. 2012, 10:22

Concernant le filtre WHERE de la première requête SQL, dans la mesure où je veux afficher uniquement les livres par auteur, je suis obligé de filtrer sinon le total du calcul s'effectue sur l'ensemble de la base.

Eléphanteau du PHP | 11 Messages

08 juil. 2012, 11:02

Je n'ai pas regardé ton code en détail, mais à première vue, si pour charger ta liste sur la première page tu as besoin de passer le paramètre id, il y a de fortes chances que tu en ais également besoin sur ta seconde page pour afficher les résultats suivants.

En gros, ton lien vers la page 2 devrait être du genre .php?id=XXX&page=2 et non pas juste .php?page=2
Que dois-je faire pour reprendre mon paramètre id pour pouvoir le générer dans .php?=XXX&page=2 ? Dois-je utiliser un masque ? ou quelque chose comme .php?id=' $_GET['id']'&page=2 ? Pour ce dernier exemple mon code n'est pas valide.

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

08 juil. 2012, 11:06

Faut des points pour concaténer des chaines et des variables ;)
$menu .= '<li><a href="' . $page_name . '?id=' . $_GET['id'] . '&page=' .($page + 1) . '"> NEXT >></a></li>';
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Eléphanteau du PHP | 11 Messages

08 juil. 2012, 11:20

Merci :D .
Le lien fonctionne bien maintenant.
Par contre je viens de découvrir un autre problème via le lien, je n'ai pas le nombre exact de livres qui s'affiche, pourtant un print_r sur ma première requête m'indiquait bien le nombre exact ! Pour l'auteur id=2, je dois avoir 4 livres qui s'affichent, j'en ai deux sur ma première page qui correspondent bien à mon paramètre $limit, mais j'en ai qu'un seul qui s'affiche lorsque je clique sur mon lien. Je vais tenter de creuser ça!

ViPHP
ViPHP | 2577 Messages

09 juil. 2012, 09:41

Bonjour,

Ca ressemble à un problème d'offset entre 0 et 1 pour le début. La première page afficherai le 2 et le 3 et la seconde la 4ème.
Il me semble que c'est 1 puis 3 pour mysql, mais ca reste à vérifier avec 0 et 2.

Eléphanteau du PHP | 11 Messages

09 juil. 2012, 11:47

Merci pour tes réponses Mazarini. J'ai trouvé le problème. Deux choses n'allaient pas. Tout d'abord, je m'excuse de vous avoir induit en erreur.

Après une vérification sur ma base de données, il y avait non pas 4 livres pour l'auteur en question mais trois.
Cependant la page m'affiche un lien supposé vers un autre livre.
En ajoutant un print_r après la première requête, sur la variable $data qui compte le nombre de livres par auteur, j'avais "quatre" comme résultat ! pour trois livres dans la base de données!!!

Le constat est que ma requête SQL n'était pas bonne. J'étais tellement obnubilé par la navigation que j'en ai oublié la requête :oops: .

En fait tu avais raison, en aucun cas auteurs.id = à livres.id. Quelle stupidité!!!

La clé secondaire (table auteurs, auteurs=id = table livres, livres.auteur_id) dans ma table livres est livres.auteur_id, qui doit être égal à id dans where. Pour établir le compte, je n'ai plus besoin de jointure .

Cependant je me retrouve avec un problème identique :
je continue à avoir des liens qui s'affiche même quand tout les livres sont affichés. Et en cliquant sur ce lien une page sans données s'affiche !
Je ne comprends pas pourquoi sur un print_r($data), j'ai toujours un 4 qui s'affiche quelque soit l'id de l'auteur entré en paramètre ! :(
Si le problème vient de l'offset, je ne vois pas quoi afficher d'autre si je veux que les pages s'affichent à compter du premier enregistrement sur la page 1. C'est d'ailleurs le cas.
<?php
include_once('connections/connect.inc.php') ;

class Pagination{

public static function getPagerData($nb_pages, $limit, $page){
   
    $nb_pages = ceil($nb_pages / $limit);
    $page = max($page, 1);
    $page = min($page, $nb_pages);
    
    $offset = ($page - 1) * $limit;
    
    $ret = new stdClass;

    $ret->offset   = $offset;
    $ret->limit    = $limit;
    $ret->nb_pages = $nb_pages;
    $ret->page     = $page;
  
    return $ret;
}
}

$nom_page = htmlentities($_SERVER['PHP_SELF']);
$limit = 2;
if(!isset($_data))
 {
    try
    {
		$bdd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $query = "
		SELECT 		
		count(livres.id)
		AS total 
		FROM livres
		WHERE livres.auteur_id=id";						
        $req = $bdd->prepare($query);
		try {
        	$req->execute();
        	}
       catch(PDOException $e) {
       		die('Erreur MySQL : ' . $e->errorInfo[2]);
        	}
        $data = $req->fetch(PDO::FETCH_COLUMN);
		    }
    catch (Exception $e)
    {
        $data = 0;
    }
 }  
    if( filter_has_var(INPUT_GET, "page") == false)
    {
        $page = 1;
    } 
    elseif(filter_var($_GET['page'], FILTER_VALIDATE_INT, array("min_range"=>1, "max_range"=>$data)) == false)
     {
        $page = 1;
    }
    else
    {	
        $page = (int)$_GET['page'];		
    }        

 if($data == 0)
 {
    $content = 'Il n\'y a pas de données.';
 }
 else
 {   
    $pagination = Pagination::getPagerData($data, $limit, $page);
   
    $offset = $pagination->offset;
    $limit  = $pagination->limit;
    $page   = $pagination->page;
	    
   $menu_pagination = '';    
  
    if($page != 1)
    {
       $menu_pagination .= '<li><a href="'.$nom_page.'?id=' . (int)$_GET['id'] . '&page='.($page - 1).'"><< précédent </a></li>';
    }
   
    for ($i = 1; $i <= $pagination->nb_pages; $i++)
    {
        if ($i == $pagination->page)
        {
           $menu_pagination .= '<li class="selected">'.$i.'</li>';
        }
        else
        {
           $menu_pagination .= '<li><a href="'.$nom_page.'?id=' . (int)$_GET['id'] . '&page='.$i.'">'.$i.'</a></li>'."\n";
        }
    }
   
    if ($page < $pagination->nb_pages)  
    {
       $menu_pagination .= '<li><a href="'.$nom_page.'?id=' . (int)$_GET['id'] . '&page='.($page + 1).'"> suivant >></a></li>';
    }
$bdd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$query = <<<EOQ
SELECT
livres.id,	
livres.titre,
livres.sous_titre,
livres.lien_img,
livres.parution,
livres.resume,
livres.prix,		
auteurs.prenom_nom AS auteur_nom,
auteurs.id AS auteur_id,
auteurs.lien_img AS auteur_img,
auteurs.biographie
FROM livres
INNER JOIN 	auteurs
ON	auteurs.id = livres.auteur_id
WHERE auteurs.id = :id
LIMIT :limit
OFFSET :offset
EOQ;
$req = $bdd->prepare($query);
$req->bindParam(':limit', $limit, PDO::PARAM_INT);
$req->bindParam(':offset', $offset, PDO::PARAM_INT);
$req->bindValue(':id', (int)$_GET['id'], PDO::PARAM_INT);
try {
   $req->execute();
}
catch(PDOException $e) {
   die('Erreur MySQL : ' . $e->errorInfo[2]);
}
	
$res = $req->fetchAll(PDO::FETCH_ASSOC);
$content = '';
    foreach ($res as $row)
    {
        $content .= '
        <article id="content2">
        	        <img src="img/cover_img/'.$row['lien_img'].'.png" alt="" id="cover">   
        	        <h2 class="titre"><a href="livre_numerique.php?id='.$row['id'].'">'.$row['titre'].'</a></h2>
        	        <h3 class="titre">'.$row['sous_titre'].'</h3>
        	        <p>Paru le : '.$row['parution'].'
       	          </p>
        	        <p>Description : '.$row['resume'].'</p>
        	        <p class="prix">À partir de : '.$row['prix'].' €</p>
        	    </article>';
	}	
 }
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="stylesheet/basestyle.css" />
<link rel="stylesheet" href="stylesheet/auteurs.css" />
<title>DeemSoom : livre jeunesse par auteur</title>
</head>
<body>
	<div id="bloc_page">
  		<header>
			<img src="img/basestyle_img/logo.png" alt="logo DeemSoom" id="logo"/>   	
        	<div id="open_it">
            	<img src="img/basestyle_img/squirrel_log.png" alt="zèbre" id="img_log">    	    
   			</div>
				<nav id="nav_1">
					<ul>
        				<li><a href="categories.php?id=1" class="0/3">0/3</a><span class="0/3ans">ans</span></li>
						<li><a href="categories.php?id=2" class="3/6">3/6</a><span class="3/6ans">ans</span></li>
						<li><a href="categories.php?id=3" class="6/9">6/9</a><span class="6/9ans">ans</span></li>
						<li><a href="categories.php?id=4" class="9/13">9/13</a><span class="9/13ans">ans</span></li>
						<li><a href="categories.php?id=5" class="13/+">13</a><span class="13ans/+">ans/+</span></li>
					</ul>
				</nav>
	  	</header>
        	<?php include("navigation.php"); ?>
            <?php include("recherche.php"); ?>
    	<section id="section1">
            	<article id="content1">
               		<img src="img/auteurs_img/<?php echo $row['auteur_img']; ?>.png" alt="" id="content1_cover">
					<h1><?php echo $row['auteur_nom']; ?></h1>
                    <p><?php echo $row['biographie']; ?></p>
                </article> 
              
       	       <?php echo $content; ?>
               <ul id="page"> 	  
               	<?php echo$menu_pagination; ?>
               </ul>  
        </section> 
        <?php include("pied.php"); ?>
    </div>
</body>
</html>
<?php
$bdd=NULL; 
?>

ViPHP
ViPHP | 2577 Messages

09 juil. 2012, 13:30

Je verrai plutot :
SELECT     count(livres.id)
                AS total 
                FROM livres
                WHERE livres.auteur_id=$id";  
ou $id est l'idenfiant de l'auteur des livres que tu utilises dans la requete d'affichage ($_GET['id']).

Eléphanteau du PHP | 11 Messages

09 juil. 2012, 13:37

Dans ce cas, j'obtiens l'erreur SQL suivante :

Erreur MySQL : You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 5

Eléphanteau du PHP | 11 Messages

09 juil. 2012, 13:56

mais en ajoutant un petit : if (isset($_GET[id])) {
$id = $_GET[id];
}
else ($id= 1
); // pour éviter l'affichage de l'erreur SQL quand l'id n'est pas indiqué.
ça va beaucoup mieux.

Je pense que cette fois-ci c'est bon.

Merci beaucoup pour l'aide.