8766 sujets

Développement web côté serveur, CMS

Bonjour,

Cette discussion fait suite à ce sujet.

Passer d'une requête simple à une requête préparée sans être spécialiste n'est pas chose facile car les changements interviennent aussi sur le code en AVAL de la requête.

Je prends l'exemple d'un petit SELECT.

Requête simple en PHP :

$connexion = mysql_connect ("localhost", "mysql_user", "mysql_password");

$requete = "SELECT champ_1 FROM base WHERE id='" . intval ($ref) . "'  LIMIT ";

$resultat = mysqli_query ($connexion, $requete);

$nbr = mysqli_num_rows ($resultat);

$retour = mysqli_fetch_assoc ($resultat);


Requête préparée (sauf erreur) :

$stmt = mysqli_prepare ($connexion, "SELECT champ_1 FROM base WHERE id = (?) LIMIT 1");

$id = intval ($ref);

mysqli_stmt_bind_param ($stmt, 'i', $id);

mysqli_stmt_execute($stmt);

$nbr = mysqli_stmt_num_rows ($stmt)

Pour commencer je ne trouve pas l'équivalent de mysqli_fetch_assoc...

Merci de votre aide.
Modifié par boteha_2 (01 Nov 2024 - 18:07)
Bonjour,

Je n'arrive pas à récupérer à la fois le nombre de lignes retournées et le tableau associatif des résultats.

D'après ce que j'ai lu, pour activer mysqli_stmt_num_rows il faut activer d'abord mysqli_stmt_store_result.

Mais une fois activé mysqli_stmt_store_result je n'arrive pas à injecter la bonne valeur dans mysqli_srmt_fetch_array car il devient impossible d'appeler mysqli_stmt_get_result.

Par ailleurs je n'ai pas compris si mysqli_stmt_fetch_array ($retour, MYSQLI_ASSOC); retourne tout le tableau (comme fait mysqli_fetch_assoc ($resultat)) ou juste la première ligne.

$requete = "SELECT cate FROM base WHERE id = ? LIMIT 1";

$stmt = mysqli_prepare ($connexion, $requete);

$id = intval ($id);

mysqli_stmt_bind_param ($stmt, 'i', $id);

mysqli_stmt_execute($stmt);

mysqli_stmt_store_result($stmt);

$nbr = mysqli_stmt_num_rows ($stmt);

// C'est bon, je récupère le bon nombre de lignes

$retour = mysqli_stmt_get_result ($stmt);

$retour = mysqli_stmt_fetch_array ($retour, MYSQLI_ASSOC);

// Là c'est erreur fatale.


Pouvez-vous m'aider ?

Merci d'avance.
Salut,

petite question ("con" qui n'aide pas mais bon) :
- Pourquoi est ce que tu utilise les fonctions "procédurales" ?

Perso je ne suis pas super fan, ça fait utiliser des noms de fonction a rallonge dans lesquelles tu dois à chaque fois passer $stmt en paramètre.
Cela me semble être un des cas où je trouve plus simple/lisible d'utiliser les fonctions "objets" ( et si tu n'as jamais vu la programmation orienté objet ça peut être l'occasion de commencer à comprendre un peu le principe sans avoir besoin de trop rentrer dans le détail).

Cela fait trois plombes que je n'ai pas fais de mysqli, mais en très gros tu vas créer un objet $stmt au départ puis tu pourras t'en servir pour appeler les différentes fonctions ("méthodes" pour utiliser le bon terme dans le cadre d'un objet). Pour accéder aux méthodes d'un objet c'est avec la notation ->. Pour illustrer : mysqli_stmt_execute($stmt); deviendra un simple $stmt->execute();

Hop petit edit pour ajouter un lien vers une page qui permet de voir les 2 notations (en haut objet et en bas procédurale) : https://www.w3schools.com/php/func_mysqli_stmt_init.asp
Modifié par Mathieuu (05 Nov 2024 - 09:30)
Bonjour Mathieuu,

Merci de ton suivi.

Je connais le style orienté objet mais je style procédural ne me dérange pas.

Merci pour ton lien, j'ai retenu deux fonctions :

 // Bind result variables
  mysqli_stmt_bind_result($stmt, $district);

  // Fetch value
  mysqli_stmt_fetch($stmt);


Mon problème est de trouver les équivalents après requêtes préparées de :

$nbr = mysqli_num_rows ($resultat);

$retour = mysqli_fetch_assoc ($resultat);
En complément du message de Mathieuu, les syntaxes procédurale et objet sont également décrites sur la doc : https://www.php.net/manual/fr/mysqli.quickstart.dual-interface.php

Un exemple simple avec mysqli :
<?php

$driver = new mysqli_driver();
$driver->report_mode = MYSQLI_REPORT_ALL;

$mysqli = new mysqli('localhost', 'root', '', 'mydb');

// fetch_assoc
$stmt = $mysqli->prepare('SELECT id, email FROM user WHERE id < ?');
$search = $_GET['search'] ?? 0;
$stmt->bind_param('i', $search);

$stmt->execute();
$result = $stmt->get_result();

while ($row = $result->fetch_assoc()) {
    echo $row['id'], ' ', $row['email'];
}

// fetch_all
$stmt = $mysqli->prepare('SELECT id, email FROM user WHERE id < ?');
$search = $_GET['search'] ?? 0;
$stmt->bind_param('i', $search);

$stmt->execute();
$result = $stmt->get_result();

$users = $result->fetch_all(MYSQLI_ASSOC);

foreach ($users as $user) {
    echo $user['id'], ' ', $user['email'];
}


Quitte à refaire ce code, tu peux aussi regarder l'API PDO à la place de mysqli :
<?php

$pdo = new PDO('mysql:host=localhost;dbname=mydb', 'root', '', [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);

// fetch
$stmt = $pdo->prepare('SELECT id, email FROM user WHERE id < :id');
$stmt->execute([':id' => $_GET['search'] ?? 0]);

while ($row = $stmt->fetch()) {
    echo $row['id'], ' ', $row['email'];
}

// fetchAll
$stmt = $pdo->prepare('SELECT id, email FROM user WHERE id < :id');
$stmt->execute([':id' => $_GET['search'] ?? 0]);
$users = $stmt->fetchAll();

foreach ($users as $user) {
    echo $user['id'], ' ', $user['email'];
}

Modifié par Pitet (06 Nov 2024 - 12:13)
Bonjour Pitet,

Merci de ton suivi.

J'ai un code existant en mysqli, je préférerais rester en mysqli, pourquoi pas style objet.

Par contre j'ai deux remarques.

$nbr = mysqli_num_rows ($resultat);
Il n'y a pas d'équivalent dans ton code.

$retour = mysqli_fetch_assoc ($resultat);
Là je récupère tout la tableau à traiter dans une boucle WHILE.

Après requête préparée il faut lancer le WHILE sans avoir le tableau.
while ($row = $result->fetch_assoc())
Pas sûr d'avoir compris ta dernière remarque.
Mon précédent extrait de code mysqli montre 2 manières de récupérer les données, soit ligne par ligne avec fetch_assoc, soit toutes les lignes avec fetch_all.

Le nombre de résultat est retourné par la méthode $result->num_rows

<?php

$driver = new mysqli_driver();
$driver->report_mode = MYSQLI_REPORT_ALL;

$mysqli = new mysqli('localhost', 'root', '', 'mydb');

$stmt = $mysqli->prepare('SELECT id, email FROM user WHERE id < ?');
$search = $_GET['search'] ?? 0;
$stmt->bind_param('i', $search);

$stmt->execute();
$result = $stmt->get_result();

while ($row = $result->fetch_assoc()) {
    echo $row['id'], ' ', $row['email'];
}

echo 'nb : ', $result->num_rows;