[RESOLU] [mysqli] Récupérer un tableau de résultats avec une requête préparée

Eléphant du PHP | 65 Messages

31 mai 2016, 11:22

Bonjour à tous,
Je voudrais savoir comment faire pour récupérer un array dans une requête préparée avec l'extension mysqli, comme le ferait un $query->fetch_assoc(). Je ne suis pas sûr que la solution que j'ai trouvé soit la plus "propre"...
La voici :

Code : Tout sélectionner

$stmt = $mysqli->stmt_init(); $stmt->prepare("SELECT id, nom FROM maTable"); $stmt->execute(); $result = $stmt->get_result(); /** * Au choix, soit une boucle while soit un fetch_all() **/ while ($row = $result->fetch_assoc()): $data[] = $row; endwhile; $data = $result->fetch_all(); $stmt->close();
Au passage, pourriez-vous m'expliquer clairement la différence entre get_result() et store_result() ? C'est assez obscure...

Avatar du membre
Mammouth du PHP | 1609 Messages

31 mai 2016, 12:21

Bonjour carte-sd, je suis pas du tout connaisseur de mysqli ne l'ayant jamais utilisé mais de ce que j'ai vu ton code est très bien, seules les 2 premières lignes pourraient être simplifiées. Apparemment tu pourrais faire un :
$stmt = $mysqli->prepare("SELECT id, nom FROM maTable");
Et pour get_result() et store_result() tout ce que je peux te dire c'est que ces 2 méthodes servent bien à faire 2 choses différentes, get_result servant a récupérer le jeu de résultats (permettant ensuite de travailler avec) alors que store_result sert uniquement à le "stocker" (la chose étant assez vague et apparemment utile seulement dans des cas bien particuliers).
Développeur web depuis + de 20 ans

Eléphant du PHP | 65 Messages

31 mai 2016, 14:53

Le stmt_init() c'est surtout pour la sémantique, je suis très carré.
Concernant store_result(), voilà qui est encore plus curieux, dans la doc officielle, ils s'en servent pour faire un simple num_rows. on dirait que eux-mêmes ne savent pas très bien à quoi ça sert... :oops:
http://php.net/manual/fr/mysqli-stmt.store-result.php
Merci pour ton aide dans tous les cas.

Avatar du membre
Mammouth du PHP | 1609 Messages

31 mai 2016, 15:06

Et bien à priori, je ne suis pas sûr de vraiment bien comprendre et tout ce que je vais dire n'est que supposition mais le but étant de "stocker le jeu de résultats complet par le client" j'imagine que quand on n'utilise pas le stock_result, la lecture des résultats se fait par communication entre le serveur web et le serveur de base de données alors que si on a appelé le stock_result, alors les données sont stockées dans la mémoire du serveur web et leur lecture n'implique plus de communication entre les deux serveurs... cela doit avoir une utilité dans certains cas. Toujours est-il qu'il me semble avoir lu que ça n'avait pas vraiment d'impact sur les performances. Donc à moins d'en avoir la nécessité et donc de savoir pourquoi on s'en sert, je pense que tu peux laisser ça de côté. ;)

PS : sachant qu'en plus tu as une propriété num_rows sur le mysqli_result. Et l'utilisation du num_rows sur le mysqli_stmt qui nécessiterait l'appel à store_result aurait tendance à confirmer mes suppositions étant donné que mysqli_stmt semblerait ne pas savoir combien il y a de lignes car il ne les auraient pas toutes parcourues... et d'ailleurs dans un cas comme dans l'autre le mysqli_result doit lui de toute manière contenir toutes les données en mémoire côté serveur web, ces données étant à priori remontées lors de l'appel du get_result. Ça pourrait donc avoir une utilité par exemple si tu veux savoir le nombre de lignes mais que tu n'as pas besoin de toutes les parcourir, mais la encore une requête count avec lecture du résultat me semblerait plus appropriée...
Développeur web depuis + de 20 ans

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

01 juin 2016, 09:57

Bonjour,

mysqli::store_result() est une méthode historique (php 5.0) qui permettait de récupérer tous les enregistrements retournés par la requête SQL.
Ceux-ci sont mis en cache côté php lors du premier fetch() qui n'a ainsi plus besoin de solliciter le serveur MySQL. A éviter pour de gros volume de données et/ou si la mémoire allouée à php est insuffisante.
Cela permettait notamment de faire du data_seek() alors que mysqli::use_result() (php 5.0) qui récupérait les résultats un par un ne le permettait pas.

mysqli::get_result() est apparue avec php 5.3 à priori pour des questions de performances et produit effectivement le même résultat que store_result() mais sans stocker l'ensemble des données renvoyées par MySQL en cache. Lors du second fetch(), php sollicitera le serveur MySQL pour connaitre la valeur suivante au lieu de la récupérer en mémoire.

Ceci étant, il y a en général réellement peu d'intérêt à utiliser des requêtes préparées pour faire un SELECT. L'objectif des requêtes préparées est d'optimiser l'exécution de celles-ci lorsqu'elles sont exécutées plusieurs fois à la suite avec des paramètres différents (ex : insert en masse ... ). On défini alors la structure de la requête qui est mémorisée et on transmet ensuite en masse les valeurs à utiliser.
Si la requête ne doit être exécutée qu'une seule fois, cela ne sert donc à rien :) Seul avantage c'est de ne pas s'encombrer avec les real_escape pour protéger les données ou de se poser la question de la nécessité d'apostrophes pour délimiter les chaines qui seront gérés par le bind :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Eléphant du PHP | 65 Messages

01 juin 2016, 10:51

Effectivement Saian, ton intuition était la bonne, store_result() stock le résultat alors que get_result() le lit, mais pourquoi cette différence ? Mon acharnement a fini par payer; cela a une utilisation particulière, comme est venu le souligner Ryle :
Les curseurs !!! Voici la grosse différence entre mysqli et PDO.
J'ai découvert ça juste avant de lire la réponse de Ryle, moi qui pensais avoir fait une grande découverte :/