IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PHP & Base de données Discussion :

Une apostrophe dans une valeur.


Sujet :

PHP & Base de données

  1. #1
    Membre très actif
    Homme Profil pro
    Apprenti perpétuel
    Inscrit en
    Novembre 2012
    Messages
    194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Apprenti perpétuel

    Informations forums :
    Inscription : Novembre 2012
    Messages : 194
    Par défaut Une apostrophe dans une valeur.
    Bonjour à toutes et tous,

    Oups, je n'y avais pas pensé avant... J'ai un nouveau membre de mon site dont le nom contient une apostrophe.
    Son nom figure bien dans ma base de donnée et il est stocké ainsi: 'O\' Dox',
    (Visible ainsi lorsque j'ouvre le document .sql avec mon éditeur de code)

    Vous trouverez ci-dessous un extrait de mon code en 3 phases:
    1- Petit formulaire d'entrée classique.
    2- Réception du POST avec un SANITIZE, vérification si déjà présent dans la BD, sinon echo formulaire de confirmation d'entrée.
    3- Réception du POST (hidden) sans SANITIZE (puisque déjà éffectué), vérification si déjà présent dans la BD, sinon insertion dans la BD.

    Le problème est le suivant, la valeur peut être entrée dans la BD.
    Mais elle n'apparait pas si elle rappelée par l'intermédiaire d'un SANITIZE.
    Par contre, elle apparait si elle rappelée sans SANITIZE.

    Puisque que ça bug quelque part, je me suis aidé avec un petit var_dump pour voir les variables:

    A la 2ème phase, le var_dump donne ceci:
    C:\wamp\www\Regist.php:106:string 'O & # 3 9 ; Dox' (length=10) (J'ai rajouté des espaces pour éviter une conversion automatique)
    C:\wamp\www\Regist.php:106:int 0

    A la 3ème phase, le var_dump donne ceci:
    C:\wamp\www\Regist.php:150:string 'O' Dox' (length=6)
    C:\wamp\www\Regist.php:150:int 1

    Vous remarquerez ci-dessus la différence de valeur et de résultat.
    Dans la 2ème phase, l'apostrophe est remplacée par " & # 3 9 ; " (effet du SANITIZE, je suppose) et la requête SQL retourne 0 rangée. (J'ai rajouté des espaces pour éviter une conversion automatique)
    Dans la 3ème phase, l'apostrophe est à nouveau une simple apostrophe et la requête SQL retourne 1 rangée.

    Conclusion, sans SANITIZE, ça marche. Avec le SANITIZE, ça bug...
    Mais ce n'est pas raisonnable de ne pas faire un SANITIZE... N'est-ce pas?
    Alors que faire?

    Vous trouverez ci-dessous un extrait de mon code:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    <?php
     
    // 1- Petit formulaire d'entrée, ci-dessous:
     
    echo '<form action="Regist.php" method="post">
    <p>Family name: <input type="text" name="FamilyName" maxlength="16" /></p>
    <p><input type="submit" name="Register" value="Enter" /></p></form>';
     
    $MyBase=new mysqli(BDHost,BDUser,BDPass,BDName);
     
    // 2- Réception du POST avec un SANITIZE, vérification si déjà présent dans la BD, sinon echo formulaire de confirmation d'entrée.
     
    if (isset($_POST['Register'])) {
    	$FamilyName=filter_var(trim($_POST['FamilyName']),FILTER_SANITIZE_STRING);
    	$Result=$MyBase->query('SELECT * FROM members WHERE FamilyName="'.$FamilyName.'"');
    	$N=$Result->num_rows;
    	var_dump($FamilyName);
    	var_dump($N);
    	if ($N==0) {echo '<form action="Regist.php" method="post">
    	<input type="hidden" name="FamilyName" value="'.$FamilyName.'" />
    	<p><input type="submit" name="RegistConfirm" value="Confirm." /></p></form>';} $Result->free();}
     
    // 3- Réception du POST sans SANITIZE (puisque déjà éffectué), vérification si déjà présent dans la BD, sinon insertion dans la BD.
     
    if (isset($_POST['RegistConfirm'])) {
    	$FamilyName=$_POST['FamilyName'];
    	$Result=$MyBase->query('SELECT * FROM members WHERE FamilyName="'.$FamilyName.'"');
    	$N=$Result->num_rows;
    	var_dump($FamilyName);
    	var_dump($N);
    	if ($N==0) {$Action=$Base->prepare('INSERT INTO members (FamilyName) VALUES (?)');
    		$Statement->bind_param('s', $FamilyName); $RegDone=$Statement->execute();} $Result->free();}
     
    $MyBase->close();
    ?>

  2. #2
    Expert confirmé Avatar de Toufik83
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2012
    Messages
    2 513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2012
    Messages : 2 513
    Par défaut
    Citation Envoyé par olivierdauxais
    Son nom figure bien dans ma base de donnée et il est stocké ainsi: 'O\' Dox'
    Les valeurs doivent être stockées en brute dans ta table mysql, pas d'échappement et pas de caractères incompréhensibles...

  3. #3
    Membre très actif
    Homme Profil pro
    Apprenti perpétuel
    Inscrit en
    Novembre 2012
    Messages
    194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Apprenti perpétuel

    Informations forums :
    Inscription : Novembre 2012
    Messages : 194
    Par défaut
    Merci Toufik83,

    Je vais essayer ce que tu proposes.
    L'échappement a été fait automatiquement lors de la requête écrite dans mon code.

  4. #4
    Expert confirmé Avatar de Toufik83
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2012
    Messages
    2 513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2012
    Messages : 2 513
    Par défaut
    Si j'étais toi, je passe directement à PDO sans me casser la tête ni avec l'encodage ni avec l'échappement.

    Tu peux exécuter ce code dans une nouvelle page, et teste l'insertion des apostrophes et des accents aussi (é,à...).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
     
    <!DOCTYPE html>
    <html>
    <head><meta charset="utf-8" /></head>
    <body><!--Séparer le code html du code php -->
             <form action="" method="post">
                  <p>Family name: <input type="text" name="FamilyName" maxlength="16" /></p>
                  <p><input type="submit" name="Register" value="Enter" /></p>
             </form>
     
    <?php
    define('BDHost',"localhost");
     define('BDUser',"...");
     define('BDPass',"...");
     define('BDName',"...");
    // 1- Petit formulaire d'entrée, ci-dessous:
    try {
        $bdd = new PDO('mysql:host='.BDHost.';dbname='.BDName, BDUser, '
                   ', array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8')//encodage en utf8
        );
    } catch(Exception $e) {
          exit('Impossible de se connecter à la base de données.');
    }
    // 2- Réception du POST avec un SANITIZE, vérification si déjà présent dans la BD, sinon echo formulaire de confirmation d'entrée.
     
    if (isset($_POST['Register'])) {
    	$FamilyName=htmlspecialchars($_POST['FamilyName']);
    	$Result=$bdd->prepare("SELECT * FROM members  WHERE FamilyName=:family");//préparation propre de la requête, pas de variables concaténé !!!
    	$Result->bindParam(":family",$FamilyName,PDO::PARAM_STR);//PDO::PARAM_STR est l'équivalent de filter_var... en PDO
    	$Result->execute();
    	$N=$Result->rowCount();
     
    	if ($N==0) {
                ?>
               <form action="" method="post">
    	         <input type="text" name="FamilyName" value="<?=$FamilyName;?>" /><!-- l'input est visible juste pour voir à quoi ressemble ce qu'on vient d'écrire...., tu peux le mettre en hidden comme au départ...-->
    	         <p><input type="submit" name="RegistConfirm" value="Confirm." /></p>
               </form>
            <?php
            }
    	else{
            ?>
    		<a style='color:red;font-size:15px'>Ce Nom existe déjà !</a>
    	<?php
            } 	
    }
     
    // 3- Réception du POST sans SANITIZE (puisque déjà éffectué), vérification si déjà présent dans la BD, sinon insertion dans la BD.
     
    if (isset($_POST['RegistConfirm'])) {
    	$FamilyName=htmlspecialchars($_POST['FamilyName']);
    	$Result=$bdd->prepare('SELECT * FROM members WHERE FamilyName=?');
    	$Result->execute([$FamilyName]);
    	$N=$Result->rowCount();
     
    	if ($N==0) {
                    $Action=$bdd->prepare('INSERT INTO members (FamilyName) VALUES (:family)');//préparation propre de la requête, pas de variables concaténé !!!
    		$Action->bindValue(':family',$FamilyName,PDO::PARAM_STR); 
    		$RegDone=$Action->execute();
    	} else{
    		?>
                      <a style='color:red;font-size:15px'>(RegistreConfirm) : Ce Nom existe déjà !</a>
    	        <?php
            }
    }
     
    $bdd=null;
    ?>
    </body>
    </html>

  5. #5
    Membre très actif
    Homme Profil pro
    Apprenti perpétuel
    Inscrit en
    Novembre 2012
    Messages
    194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Apprenti perpétuel

    Informations forums :
    Inscription : Novembre 2012
    Messages : 194
    Par défaut
    Merci Toufik83,

    Oui, en effet, PDO est certainement plus simple mais je ne maitrise pas du tout PDO car lorsque j'ai appris le php, PDO n'existait pas et je n'ai pas encore pris la peine de me pencher dessus... Et puisque mon site a environ 10.000 lignes en procédural, je reste pour le moment en procédural... Mais je garde en tête ce que tu as dis... J'ai fait un copié/collé de ton code et je m'en servirai le jour où je vais m'amuser à recoder tout mon site en PDO... Un jour !!!

    Dans l'immédiat, je crois que je vais simplement essayer de Sanitizer aussi dans la 3eme phase quand bien c'est un peu idiot de le refaire puisque il a été fait en 2ème phase, mais cela reconvertira en brut le "reformatage automatique" lié au POST en hidden... Il me faudra, évidement, modifier les vieilles données déjà entrées dans la base afin d'harmoniser le contenu de ma base et de remplacer l'apostrophe échappée par sa valeur html "& # 3 9 ;" (J'ai mis des espaces pour éviter une conversion automatique sur cette page de forum).

    Encore merci pour ton aide.

  6. #6
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    1- tu confonds PDO et POO.

    2- Quant à "SANITIZE", tu te donnes beaucoup de mal, alors que tes requêtes SQL sont de vraies passoires...

  7. #7
    Expert confirmé Avatar de Toufik83
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2012
    Messages
    2 513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2012
    Messages : 2 513
    Par défaut
    Oui, tu confonds entre PDO et POO.

    J'ai seulement converti ton code mysqli en PDO c'est tout, et il n y aura aucun impact sur ton site si tu intègres le code tel qu'il est.

  8. #8
    Invité
    Invité(e)
    Par défaut
    1- @Toufik83

    ton code (de connexion SQL) est en PDO "orienté objet".
    (il n'y a pas de syntaxe "procédurale" de PDO).


    2- Tout comme celui d'olivierdauxais est en mysqli "orienté objet".
    ex. :
    • $mysqli->query(...) : "orienté objet"
    • mysqli_query($link, ...) : "procédural"


    3- Comme quoi, on peut avoir :
    • une syntaxe "orientée objet" pour le code de connexion SQL,
    • tout en ayant un code PHP "procédural" pour le reste.


    4- Perso, je ne fais pas de POO, mais j'utilise PDO.
    Et surtout, les requêtes préparées.
    Dernière modification par Invité ; 21/06/2019 à 15h47.

  9. #9
    Membre très actif
    Homme Profil pro
    Apprenti perpétuel
    Inscrit en
    Novembre 2012
    Messages
    194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Apprenti perpétuel

    Informations forums :
    Inscription : Novembre 2012
    Messages : 194
    Par défaut
    Merci pour ces précisions.
    Je suppose que POO veut dire "Programmation Orienté Objet". Est-ce exact?
    Et que veut dire PDO?

    2- Quant à "SANITIZE", tu te donnes beaucoup de mal, alors que tes requêtes SQL sont de vraies passoires...
    @Dalmatien: Quel code me proposerais-tu pour que mes requêtes SQL ne soient pas de vraies passoires et qui, en plus, me donnerait moins de mal?

    Pour les autres débutants comme moi: Gardez en tête qu'un POST hidden annulera en partie un "formatage" realisé par un SANITIZE:
    Le caractère de l'apostrophe est concerné par ce "reformatage". C'est exactement cela qui m'a joué des tours et qui est à l'origine de ce fil dans ce forum.

  10. #10
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    1- un peu de lecture :



    2- requête préparée.

    Faire une requête préparée avec mysqli_ est assez galère...
    Alors qu'en PDO, c'est tout simple.

    Sinon, avec mysqli_, il faut au minimum utiliser $mysqli->real_escape_string() sur les données externes.

  11. #11
    Membre très actif
    Homme Profil pro
    Apprenti perpétuel
    Inscrit en
    Novembre 2012
    Messages
    194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Apprenti perpétuel

    Informations forums :
    Inscription : Novembre 2012
    Messages : 194
    Par défaut
    Merci cher Dalmatien pour tous ces liens.

    Mais tu ne m'as pas dit en quoi mes requêtes étaient des vraies passoires...
    Pourrais-tu justifier tes propos?

    Tu dis que PDO est beaucoup plus simple... Mais moi, le peu que j'en ai vu me donne l'impression d'un plus grand nombre de ligne de code en PDO que ma façon dans mon extrait de code au début de ce fil. Pourrais-tu me montrer 2 exemples pour une même requête dans 2 styles différents? PDO d'un coté et de l'autre: mysqli objet avec $mysqli->real_escape_string(), par exemple.

    Cela apporterait de l'eau à ton moulin plutôt que de simplement dire que c'est plus simple.
    Le dire, c'est bien... Le démontrer, c'est bien mieux !!!

  12. #12
    Invité
    Invité(e)
    Par défaut
    Tous les exemples sont dans les liens.

    Il faut LIRE.
    Pas survoler.

Discussions similaires

  1. Réponses: 1
    Dernier message: 23/01/2015, 10h50
  2. Joindre une valeur arbitraire dans un SELECT
    Par Tuxxy dans le forum Requêtes
    Réponses: 3
    Dernier message: 20/01/2004, 17h04
  3. Passer une valeur Null dans un argument de procédure
    Par preempalver dans le forum VBA Access
    Réponses: 5
    Dernier message: 30/12/2003, 20h52
  4. Lire une valeur dans le registre
    Par John.s dans le forum C
    Réponses: 2
    Dernier message: 26/11/2003, 19h55
  5. Prendre une valeur dans la grappe XML
    Par Sandrine75 dans le forum XMLRAD
    Réponses: 7
    Dernier message: 21/05/2003, 10h26

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo