Bonjour à tous.
je construis une classe BDD, pour automatiser et simplifier mes requêtes. Tout se passe bien tant qu'un champ ne contient pas d'apostrophe. J'ai immédiatement appliqué un addslashes sur mes entrées, ce qui fonctionne parfaitement, mais j'ai également lu qu'il ne fallait plus utiliser addslashes avec PDO, mais pdo::quote. Et avec pdo::quote, ça ne fonctionne plus, l'apostrophe n'est pas échappé.
Voici un extrait de mon code pour ajouter un enregistrement :

public function ajoute($table,$ajout=array()) {
        $key='';
        $val='';
        foreach($ajout as $k=>$v){
            $key .="$k,";
            $v=addslashes($v);
            // $v=$this->connexion->quote($v); ceci ne fonctionne pas !
            $val .="'$v',";
        }
        $key = substr($key,0,-1);
        $val = substr($val,0,-1);
        $this->sql="INSERT INTO ".$table." (".$key.") VALUE (".$val.")";
        // echo '<p>'.$this->sql.'</p>'; debuggage
        try {
            $r= $this->connexion->exec($this->sql);
        }
        catch(PDOException $e) {
            $this->erreur($e);
        }
        return $r;
    }

Vous noterez donc que j'utilise addslashes, car quote n'échappe pas l'apostrophe contenu dans un champ texte. (et qu'en est-il de mers() ?).
Je veux bien tenter la requête préparée, mais je souhaiterais d'abord comprendre où est le problème, que la requête préparée ne résoudra d'ailleurs pas forcément.

J'ai arpenté le net à la recherche de l'explication claire, que je n'ai toujours pas trouvée. Peut-être Grafikart.fr et sa communauté me viendra-t-elle encore une fois en aide.

Merci de m'avoir lu,

Cordialement.
Thierry.

9 réponses


thierrysudfr
Auteur
Réponse acceptée

Je crois que je passe trop de temps devant mon écran, ça ramollit le cerveau !!!!
Ce qui suit fonctionne très bien, et c'est bien ce que j'ai écris dans mes posts précédents, mais ce n'est pas ce qu'il y avait réellement dans mon code :

$v=$this->connexion->quote($v);

Dans mon code, j'avais "juste" oublié "$v=" en début de ligne !!!!!!!!!!! aaaaarrrghhhhhhh !

$this->connexion->quote($v);

Désolé de vous avoir fait perdre votre temps.
et merci.

Thierry

Tu peux montrer comment tu utilise la fonction et quelles paramètre la fait planter ?

Mon formulaire est "fabriqué" par une classe, qui cherche également les éventuelles erreurs de saisie. si tout est ok, un fichier php est include, pour gérer l'accès à la BDD. Les données postées par le formulaires sont donc dans $this->data
Imaginons une table avec ID , prenom et commentaire.
La saisie prenom="pierre" , commentaire="je mange la pomme" fonctionne.
La saisie prenom="pierre" , commentaire="je mange l'orange" ne fonctionne pas avec quote. L'erreur mysql indique bien que le problème se situe à partir de orange. En affichant la requête, on se rend d'ailleurs compte que l'apostrophe de l'orange n'est pas échappé.

Voici le code de traitement du formulaire :

<?php
$action=0; // action ajouter par défaut
$table = 'test';
$bdd2 = new connectbdd(BAD_URL,BAD_NAME,BAD_LOG,BAD_PASS);
if(isset($this->data'id']) && $this->data'id']>0 && (isset($_POST'bouton']))){
    $id=$this->data'id'];
    if($_POST'bouton']=='modifie'){
        $action=1; // enregistrement à modifier
    }
    if($_POST'bouton']=='efface' ){
        $action=2; // enregistrement à effacer
    }
}
switch ($action){
    case 0 : // enregistrement à ajouter
        foreach($this->data as $k=>$v){ // données saisies à enregistrer dans la base
            if ($k!='id' && $k!= 'bouton'){
                 if($this->regex$k]=='date' && $this->data$k]!=''){
                    $datesql=explode('/',$v);
                    $v=$datesql[2].'-'.$datesql[1].'-'.$datesql[0];
                }
                $ajout$k]=$v;
            }
        }
        $ajout'id_adherent']=$_SESSION'ident']'ad_id'];// ajoute le id adhérent
        if($bdd2->ajoute($table, $ajout)){
            $message=' Création réussie';
         }else{
            $message='Erreur d\'enregistrement dans la base, veuillez recommencer';
        }
    break;
etc.... pour modifier ou effacer.

Faut-il faire un addslashes avant le post, puis un quote dans la requête juste pour les injections sql ?

$v=$this->connexion->quote($v);

'connexion' est une instance PDO? Tu peux montrer où tu la déclare?
J'ai essayé le pdo::quote($str), ça marche chez moi.

Voici le début de la classe connectbdd, appelée par

$bdd2 = new connectbdd(BAD_URL,BAD_NAME,BAD_LOG,BAD_PASS);

(Voir le post précédent)
ps : BAD ne veut pas dire mauvais, c'est la Base de donnée de l'ADhérent, lol...

class connectbdd {
//Connexion à la base de données
    private $connexion;
    private $nbenreg;
    private $sql;

//méthodes
    public function __construct($host,$db,$user,$pass) {
        $this->host = $host ; //serveur (souvent localhost)
        $this->db = $db ; // Le nom de la base de donnee
        $this->user = $user; //login
        $this->pass=$pass ; // mot de passe

        try {
            $this->connexion = new PDO('mysql:host='.$this->host.';dbname='.$this->db, $this->user, $this->pass);
            $this->connexion->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
            $this->connexion->exec('SET NAMES utf8');
        }
        catch(PDOException $e) {
            echo 'Problème de connexion à la base de donnée';
            echo 'Erreur : '.$e->getMessage().'<br />';
            echo 'N° : '.$e->getCode();
        }
    }

Je précise que ça ne fonctionne ni sur wamp, ni chez mon hébergeur, et que magic-quote-gpc est désactivé chez moi, et activé chez mon hébergeur.
Le problème se situe forcément quelque part dans mon code, mais ouuuuuuuuuuuuuuuuuuu ?????
Ceci dit, je ferai un test ce soir avec une petite requête toute simple, sans passer par les classes, peut-être que cela me mettra sur la voie.
Mais concrètement, Tiorte et Grafikart, en uilisant pdo::quote, je dois bien obtenir quelque chose du genre : "je mange l\'orange" si je fais un echo du résultat ?

Merci en tout cas de votre intérêt.

Oui, c'est bien ça. Mais je comprend pas d'où tu sors le 'connexion' dans:

$v=$this->connexion->quote($v);

Puisque tu instancie PDO dans $bdd2, ne faudrait-il pas plutôt faire ceci:

$v=$this->bdd2->connexion->quote($v);

Je suis très peu certain du code, je débute un peu en POO, mais il me semble qu'il y a un problème de cet ordre. Cependant je ne suis pas sur que cela marche non plus, car 'connexion' est en private.
Par ailleurs, ne t'attarde pas sur PDO::quote(), il est obsolète quand tu prépare tes requêtes.

Tiorte, je suis également débutant en POO, mais là je pense que tu te trompes. En effet, $bdd2 est une instance de connectbdd, et connexion est une instance de PDO. D'ailleurs, $this->connexion fonctionne parfaitement avec exec() ou query().
Enfin, en tout cas, il me semble... Ceci dit, il y a bien une erreur quelque part...
Merci à toi t'étudier toutes les pistes.

Comme je l'ai dit plus haut , j'ai fait un petit test, et là, pdo::quote fonctione parfaitement (code ci-dessous).

<?php
$bdd=new PDO('mysql:host=localhost;dbname=mabasedetest','root','');
$bdd->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
$bdd->exec('SET NAMES utf8');
if(isset($_POST'test'])){
    $test=$_POST'test'];
    echo $test;
    $quotest=$bdd->quote($test);
    echo "<br />$quotest";
}
?>
<form method="post" action="testpdo.php">
    <input type="text" name="test" />
    <input type="submit" name="valider">
</form>

les résultats sont :
L'OLIVIER
'L\'OLIVIER'

Je vais creuser, peut-être une solution dans la soirée.

Merci.

Bon courage pour le debuggage ;)