Pagination : comment remplacer SQL_CALC_FOUND_ROWS ?

Résolu
polarbird Messages postés 104 Date d'inscription   Statut Membre Dernière intervention   -  
polarbird Messages postés 104 Date d'inscription   Statut Membre Dernière intervention   -
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 38486 Date d'inscription   Statut Modérateur Dernière intervention   4 752
 
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 104 Date d'inscription   Statut Membre Dernière intervention   1
 
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 38486 Date d'inscription   Statut Modérateur Dernière intervention   4 752
 
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 104 Date d'inscription   Statut Membre Dernière intervention   1 > jordane45 Messages postés 38486 Date d'inscription   Statut Modérateur Dernière intervention  
 
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 38486 Date d'inscription   Statut Modérateur Dernière intervention   4 752 > polarbird Messages postés 104 Date d'inscription   Statut Membre Dernière intervention  
 
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 104 Date d'inscription   Statut Membre Dernière intervention   1 > jordane45 Messages postés 38486 Date d'inscription   Statut Modérateur Dernière intervention  
 
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 38486 Date d'inscription   Statut Modérateur Dernière intervention   4 752 > polarbird Messages postés 104 Date d'inscription   Statut Membre Dernière intervention  
 
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