Pagination : comment remplacer SQL_CALC_FOUND_ROWS ?

Résolu/Fermé
polarbird Messages postés 105 Date d'inscription vendredi 24 juin 2011 Statut Membre Dernière intervention 16 décembre 2023 - 8 mai 2020 à 22:05
polarbird Messages postés 105 Date d'inscription vendredi 24 juin 2011 Statut Membre Dernière intervention 16 décembre 2023 - 9 mai 2020 à 12:32
Bonjour à tous,

Ayant récemment appris que SQL_CALC_FOUND_ROWS va disparaître, je cherche une alternative, car mon code de pagination utilise cette méthode.

Voici mon code :
$page = (!empty($_GET['page']) ? $_GET['page'] : 1);
 
$accueil = 'https://exemple.fr/'.trim($_GET['lang']).'/t-'.trim($_GET['slug']).'';
 
$type_page = '-p-';
 
$debut = ($page - 1) * $limite;
 
$query = "SELECT SQL_CALC_FOUND_ROWS
  t.art_id,
  t.tag_name,
  t.tag_slug,
  t.tag_code,
  a.id_article,
  a.date_creation
FROM
  tags t
  INNER JOIN articles a ON a.id_article = t.art_id
WHERE
  t.tag_slug = :tag_slug
ORDER BY
  a.date_creation DESC
LIMIT :limite OFFSET :debut";
 
$tag_slug = trim($_GET['slug']);
 
$query = $bdd->prepare($query);
 
$query->bindValue('limite', $limite, PDO::PARAM_INT);
$query->bindValue('debut', $debut, PDO::PARAM_INT);
$query->bindValue('tag_slug', $tag_slug, PDO::PARAM_STR);
 
$query->execute();
 
$res_nb_art = $bdd->query('SELECT found_rows()');
 
$nb_total = $res_nb_art->fetchColumn();
 
$nb_pages = ceil($nb_total / $limite);
 
echo '<br />';
echo "Page $page / $nb_pages";
echo '<br /><br>';
 
echo getPaginationString($page, $nb_total, $limite, $adj, $accueil, $type_page);


J'ai essayé en remplaçant SQL_CALC_FOUND_ROWS par COUNT, mais j'obtiens un message d'erreur avec cette requête :

SELECT COUNT(
  t.art_id,
  t.tag_name,
  t.tag_slug,
  t.tag_code,
  a.id_article,
  a.date_creation)
FROM
  tags t
  INNER JOIN articles a ON a.id_article = t.art_id
WHERE
  t.tag_slug = :tag_slug
ORDER BY
  a.date_creation DESC
LIMIT :limite OFFSET :debut


Comment faire pour obtenir le même résultat avec COUNT ou une autre méthode svp ?

Merci

2 réponses

jordane45 Messages postés 38326 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 2 décembre 2024 4 712
8 mai 2020 à 22:34
Bonjour,

Tu dois faire une seconde requête, sans limit offset comme par exemple :


SELECT COUNT( t.art_id ) as NB
FROM
  tags t
  INNER JOIN articles a ON a.id_article = t.art_id
WHERE
  t.tag_slug = :tag_slug



0
polarbird Messages postés 105 Date d'inscription vendredi 24 juin 2011 Statut Membre Dernière intervention 16 décembre 2023 1
8 mai 2020 à 22:36
Merci Jordane pour ton message. Le gros problème de ta méthode, c'est que je ne peux plus faire de pagination, puisque tu supprimes LIMIT et OFFSET, or la pagination repose justement sur l'emploi de ces deux méthodes...
0
jordane45 Messages postés 38326 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 2 décembre 2024 4 712
8 mai 2020 à 22:49
Comme je te l'ai indiqué ... il faut que tu fasses une requête supplémentaire.
Une requête pour connaitre le count et une requête qui contient les données à afficher avec limit/offset.

Si tu avais regarder la documentation... tu aurais eu la réponse.
https://dev.mysql.com/worklog/task/?id=12615
https://dev.mysql.com/doc/refman/8.0/en/information-functions.html

The SQL_CALC_FOUND_ROWS query modifier and accompanying FOUND_ROWS() function are deprecated as of MySQL 8.0.17 and will be removed in a future MySQL version. As a replacement, considering executing your query with LIMIT, and then a second query with COUNT(*) and without LIMIT to determine whether there are additional rows. For example, instead of these queries:
0
polarbird Messages postés 105 Date d'inscription vendredi 24 juin 2011 Statut Membre Dernière intervention 16 décembre 2023 1 > jordane45 Messages postés 38326 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 2 décembre 2024
8 mai 2020 à 23:32
Merci pour la doc et ta réponse. Je commence à comprendre comment faire. J'ai donc mis en œuvre ta méthode.
J'ai gardé ma première requête, et j'ai changé la deuxième (
SELECT found_rows()
que j'ai remplacé par la requête suivante :
SELECT COUNT( t.art_id ) AS nb FROM tags t INNER JOIN articles a ON a.id_article = t.art_id WHERE t.tag_slug = :tag_slug
(que tu m'avais suggéré dans ton précédent message)

Ce qui me donne le code suivant :
$page = (!empty($_GET['page']) ? $_GET['page'] : 1);

$accueil = 'https://wildenberg.su/'.trim($_GET['lang']).'/t-'.trim($_GET['slug']).'';

$type_page = '-p-';

$debut = ($page - 1) * $limite;

$query = "SELECT 
  t.art_id,
  t.tag_name,
  t.tag_slug,
  t.tag_code,
  a.id_article,
  a.date_creation
FROM
  tags t
  INNER JOIN articles a ON a.id_article = t.art_id
WHERE
  t.tag_slug = :tag_slug
ORDER BY
  a.date_creation DESC
LIMIT :limite OFFSET :debut";

$tag_slug = trim($_GET['slug']);

$query = $bdd->prepare($query);

$query->bindValue('limite', $limite, PDO::PARAM_INT);
$query->bindValue('debut', $debut, PDO::PARAM_INT);
$query->bindValue('tag_slug', $tag_slug, PDO::PARAM_STR);

$query->execute();

$res_nb_art = $bdd->query('SELECT COUNT( t.art_id ) AS nb FROM tags t INNER JOIN articles a ON a.id_article = t.art_id WHERE t.tag_slug = :tag_slug');

$nb_total = $res_nb_art->fetchColumn();

$nb_pages = ceil($nb_total / $limite);

echo '<br />';
echo "Page $page / $nb_pages";
echo '<br /><br>';

echo getPaginationString($page, $nb_total, $limite, $adj, $accueil, $type_page);


Et j'obtiens l'erreur suivante :
Fatal error: Uncaught PDOException: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ':tag_slug' at line 1 in /home/arhljqap/public_html/ts.php:86 Stack trace: #0 /home/arhljqap/public_html/ts.php(86): PDO->query('SELECT COUNT( t...') #1 {main} thrown in /home/arhljqap/public_html/ts.php on line 86

On dirait que l'erreur vient de la seconde requête.
0
jordane45 Messages postés 38326 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 2 décembre 2024 4 712 > polarbird Messages postés 105 Date d'inscription vendredi 24 juin 2011 Statut Membre Dernière intervention 16 décembre 2023
8 mai 2020 à 23:44
vu que tu utilises des variables nommé dans ta requête il faut que tu fasses de la même manière que ta précédente ...en faisant du Bindparam
0
polarbird Messages postés 105 Date d'inscription vendredi 24 juin 2011 Statut Membre Dernière intervention 16 décembre 2023 1 > jordane45 Messages postés 38326 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 2 décembre 2024
8 mai 2020 à 23:53
Merci. J'ai fait comme tu as dit, comme dans la précédente avec un bindvalue sur la variable tag_slug, et j'obtiens toujours le même message d'erreur.

Voici mon code :
$res_nb_art = $bdd->query('SELECT COUNT( t.art_id ) FROM tags t INNER JOIN articles a ON a.id_article = t.art_id WHERE t.tag_slug = :tag_slug');

$res_nb_art->bindValue('tag_slug', $tag_slug, PDO::PARAM_STR);

$nb_total = $res_nb_art->fetchColumn();
0
jordane45 Messages postés 38326 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 2 décembre 2024 4 712 > polarbird Messages postés 105 Date d'inscription vendredi 24 juin 2011 Statut Membre Dernière intervention 16 décembre 2023
Modifié le 8 mai 2020 à 23:59
Parce que ce n'est pas query qu'il faut utiliser mais prépare... Comme pour ton autre requête.
D'ailleurs je serais toi je prendrai l'habitude de ne plus utiliser query
0