PDO : Vérification avant enregistrement

Résolu/Fermé
emrh Messages postés 427 Date d'inscription mardi 9 décembre 2014 Statut Membre Dernière intervention 9 avril 2024 - 11 déc. 2014 à 23:07
emrh Messages postés 427 Date d'inscription mardi 9 décembre 2014 Statut Membre Dernière intervention 9 avril 2024 - 12 déc. 2014 à 14:30
Bonsoir à tous....

Je reprends actuellement toutes mes commandes classiques avec l'interface PDO, et
je ne trouve pas sur Internet comment faire pour vérifier qu'un enregistrement n'est
pas déjà présent dans la table avant de l'enregistrer...

Avant, je faisais comme ça :


// Sécurisation & formatage du nom de la recette :
$recette_nom = mysql_real_escape_string(htmlspecialchars($_POST['recette_nom']));
$recette_nom = mb_strtoupper($recette_nom,'UTF-8');

// Vérification de la présence ou non de la recette dans la base
$requete = "SELECT count(*) as nb FROM menu_recettes WHERE recette_nom = '".$recette_nom."'";
$req_exec = mysql_query($requete) or die(mysql_error());
$resultat = mysql_fetch_assoc($req_exec);
if (isset($resultat['nb']) && $resultat['nb'] == 0) {

Etc Etc....


Maintenant, je bloque sur un truc comme ça (exemple d'une autre page,
ne tenez pas compte des variables différentes de mon premier exemple...) :



// L'aliment est-il déja présent dans la base ?
// Sécurisation et formatage du nom de l'aliment :
$nom = strtoupper(htmlspecialchars($_POST['nom']));

// Requête comptage des aliments portant le même nom :
$sql = "SELECT * FROM menu_aliments WHERE aliment_nom= '$nom'";
$req = $bdd->exec($sql);
$resultat = $req->fectchAll();

if count($resultat) { // L'aliment n'existe pas encore, on l'enregistre :

// Libération du curseur :
$req -> closeCursor();

// Récupération et sécurisation des données du formulaire :

$classe = htmlspecialchars($_POST['classe']);

Etc, Etc...

Pour info : la partie enregistrement de l'aliment fonctionne bien, ce qui merdouille
c'est à partir du moment ou j'essaie de vérifier si l'enregistrement est déjà présent !

Merci d'avance pour vos tuyaux !

PDO : c'est vraiment pas un CADO !



6 réponses

Utilisateur anonyme
11 déc. 2014 à 23:30
Bonjour

$req->fectchAll()

Déjà, si tu écrivais fetchAll() au lieu de fectchAll, ça irait sans doute moins mal.

if count($resultat) {     // L'aliment n'existe pas encore, on l'enregistre : 

Justement si, dans ce cas, l'aliment existe déjà.

Quant à l'utilisation de htmlspecialchars pour la "sécurisation" des données, c'est une aberration. htmlspecialchars n'a jamais servi à ça, et l'un des avantages de PDO est de faciliter l'utilisation des requêtes préparées, qui rendent ce genre de cuisine inutile.
0
emrh Messages postés 427 Date d'inscription mardi 9 décembre 2014 Statut Membre Dernière intervention 9 avril 2024 20
Modifié par emrh le 12/12/2014 à 08:23
Merci le père pour ton aide sur la faute de frappe ( ou dyslexie ?) fectchAll() ;-)

(J'aurais aimé que mon Sublime Text me le colore en rouge ou mieux que
ma page html générée m'indique l'erreur au lieu de rester blanche).



En ce qui concerne htmlspecialchars, je me suis basé sur mon ancien code et sur
une mauvaise interprétation de mon bouquin du Site du Zéro (page 217 : <ital>"Il faudra bien veiller à appeler htmlspecialchars() pour protéger les chaines contre la faille
XSS"
, mais ils parlaient de l'affichage, je n'en suis pas encore là)... D'ailleurs
je n'arrive pas à comprendre pourquoi avec PDO on a plus besoin de protéger
ce qui est inséré par l'utilisateur ?


En tout cas, même modifié, ça ne fonctionne pas et mon "or die(print_r($req->errorInfo()));" est toujours muet !


<?php
header('Refresh: 4; URL= +aliment.php');

// Connexion à la base de données :
include ('connexion.php');

// Le formulaire possède t-il un champ 'nom' ?
if (isset($_POST['nom'])) {

// L'aliment est-il déja présent dans la base ?
// Formatage du nom de l'aliment :
$nom = strtoupper($_POST['nom']);

// Requête comptage des aliments portant le même nom :
$sql = "SELECT * FROM menu_aliments WHERE aliment_nom= '$nom'";
$req = $bdd->exec($sql);
echo $req;
$resultat = $req->fetchAll();

if count($resultat) { // L'aliment existe dans la base, on ne l'enregistre donc pas :
$message = 'L\'aliment '. $nom . ' fait déjà parti de la base de données, il n\'a donc pas été ajouté !';
}

else { // L'aliment n'existe pas, on peut donc l'enregistrer :

// Libération du curseur :
$req -> closeCursor();

// Récupération (et sécurisation ?) des données du formulaire :

$classe = $_POST['classe'];
$unite = $_POST['unite'];
$calorie = $_POST['calorie'];
$rayon = $_POST['rayon'];
$type = $_POST['type'];


// Préparation de la requête d'insertion :
$req = $bdd->prepare('INSERT INTO menu_aliments (aliment_nom, aliment_classe, aliment_unite, aliment_calorie, aliment_rayon) VALUES (:nom, :classe, :unite, :calorie, :rayon)');

// Exécution de la requête :
$req->execute(array(
'nom' => $nom,
'classe' => $classe,
'unite' => $unite,
'calorie' => $calorie,
'rayon' => $rayon
)) or die(print_r($req->errorInfo()));

// Message d'information :
$message ='L\'aliment ' . '<strong>' . $nom . '</strong>' . ' a bien été enregistré dans la base...' . '<br />' .
'Voici le détail :' . '<br />' . '<br />' .
'Nom : ' . $nom . '<br />' .
'Classe : ' . $classe . '<br />' .
'Unité : ' . $unite . '<br />' .
'Calories : ' . $calorie . '<br />' .
'Rayon : ' . $rayon . '<br />' .
'Type de plat : ' . $type. '<br />' . '<br />' .
"Vous allez être redirigé à la page précédente...";
}
}

else { // Le champ 'nom' n'est pas renseigné :
$message = "Un problème est survenu et votre aliment n'a pas été enregistré," . '<br />' .
"Vous allez être redirigé à la page précédente...";
}

?>
0
Utilisateur anonyme
12 déc. 2014 à 13:58
Dans ton premier message, tu te plaignais de ne pas parvenir à vérifir si un enregistrement était présent, maintenant tu te plais que "or die(print_r($req->errorInfo()));" est muet.
Peux-tu dire ce qui ne marche pas, c'est à dire :
1 - ce que tu fais,
2 - le résultat auquel tu t'attendais et
3 - ce que tu observes ?

Remarques : à quoi sert un print_r dans un die, au lieu d'un simple "or die($req->errorInfo());" ?
En ce qui concerne le besoin de protéger les données ou pas, ça ne dépend pas de PDO lui même mais du fait qu'on utilise les requêtes préparées avec des marqueurs. La fonction qui remplace ces marqueurs par les valeurs réalise elle-même les échappements de caractères nécessaires. Mais si tu n'utilises pas ces marqueurs et que tu insères toi-même tes variables dans une requête avec des concaténation sans précautions, peu importe qu'il s'agisse de PDO ou des interfaces mysql_ ou mysqli_ : ta requête sera potentiellement erronée voire dangereuse si certains caractères apparaissent dans tes données.
0
emrh Messages postés 427 Date d'inscription mardi 9 décembre 2014 Statut Membre Dernière intervention 9 avril 2024 20
Modifié par emrh le 12/12/2014 à 14:15
Merci beaucoup pour ces précisions très claires...

Pour ta répondre à ta question, je me rend compte que je me suis mal
exprimé. Je voulais dire que j'avais essayé de faire un code pour vérifier
qu'un aliment que je m'apprêtais à enregistrer dans ma table n'était pas
déjà dans la table. J'aimerai éviter un doublon en fait, pour ne pas avoir
deux fois "TOMATE" par exemple !
J'ai donc écris mon code et me suis trompé dans la syntaxe (je débute),
donc au lieu de me dire 'votre aliment a bien été ajouté' la page restait toute
blanche...comme plantée. C'est là que j'aurais aimé l'aide d'un retour de print_r($req->errorInfo()) pour savoir où j'avais merdé !
(Pour info, je n'ai pas mis le code html, mais je ne pense pas que ce soit lui qui présente problème, car quand je mets des // devant les requêtes mal écrite, la
page html apparaît).



Il semblerait que ma requête ne soit pas bonne et qu'il faudrait mieux utiliser celle ci :


// Requête comptage des aliments portant le même nom :
$req = $bdd->prepare("SELECT id FROM menu_aliments WHERE aliment_nom = :nom");
$req->execute(array('nom' => $nom));
$count = $req->rowCount();

if (count) { // L'aliment existe dans la base, on ne l'enregistre donc pas :
$message = 'L\'aliment '. $nom . ' fait déjà parti de la base de données, il n\'a donc pas été ajouté !';
}



Sauf que maintenant, j'ai toujours le même message : l'aliment est déjà présent
dans la table...
J'ai avancé, je ne suis plus sur une page blanche plantée !
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Utilisateur anonyme
12 déc. 2014 à 14:18
if (count) ou if ($count) ?
0
emrh Messages postés 427 Date d'inscription mardi 9 décembre 2014 Statut Membre Dernière intervention 9 avril 2024 20
Modifié par emrh le 12/12/2014 à 14:33
C'est ça le père ! : if($count > 0){

Je me faisais aussi aider ailleurs, voici la réponse à ma question, si cela
peut aider d'autres personnes :


// L'aliment est-il déja présent dans la base ?
// Formatage du nom de l'aliment :
$nom = strtoupper($_POST['nom']);

// Requête comptage des aliments portant le même nom :
$req = $bdd->prepare("SELECT aliment_id FROM menu_aliments WHERE aliment_nom = :nom LIMIT 1");
$req->execute(array('nom' => $nom));
$count = $req->rowCount();

if($count > 0){ // L'aliment existe dans la base, on ne l'enregistre donc pas :
$message = 'L\'aliment '. $nom . ' fait déjà parti de la base de données, il n\'a donc pas été ajouté !';
}

else { // L'aliment n'existe pas, on peut donc l'enregistrer :

// Libération du curseur :
$req -> closeCursor();

// Récupération (et sécurisation ?) des données du formulaire :

$classe = $_POST['classe'];
$unite = $_POST['unite'];


.... etc ...etc




LIMIT 1 car il n'est pas necessaire d'aller plus loin dans la recherche car il ne peut y
avoir qu'un seul aliment portant ce nom

Et j'ai appris aussi le WHERE aliment_nom = :nom
Je ne savais pas comment mettre la variable dans ma requête
(des " ou des ' avec des \ suivis de . ! ! !)

Encore merci le père pour ton aide !
0