Bonsoir,

J'ai besoin de vos lumières

Voila je vais allez droit au but ! j'ai fais une requête pour faire un update de membre via cette requête :

/ *******  
* On modifie un utilisateur inscrit
******** /
if(isset($_GET'id']) && isset($_POST'username']) && isset($_POST'activation']) && isset($_POST'slug']) && isset($_POST'avatar'])){
    checkCsrf();
    $slug = $_POST'slug'];
    $activation = $_POST'activation'];
    if(in_array($slug, array('modo', 'admin', 'non_actif', 'membre'))){
        $username = $db->quote($_POST'username']);
        $avatar = $db->quote($_POST'avatar']);
        $activation = $db->quote($_POST'activation']);
        $slug = $db->quote($_POST'slug']);
        $id = $db->quote($_GET'id']);
        if(isset($_GET'id'])){
            $id = $db->quote($_GET'id']);
           $select = $db->prepare("UPDATE users SET avatar=:avatar, username=:username, slug=:slug, activation=:activation WHERE id=:id");
       $select->execute(array
                (
                    ':avatar'=>$avatar, 
                    ':username'=>$username, 
                    ':slug'=>$slug, 
                    ':activation'=>$activation
                )
            );
        }   
        setFlash('L\'utilisateur a bien étais modifier !');
        header('Location:index.php#cat');
        die();
    }else{
        setFlash('Le slug ou activation n\'est pas valide', 'danger');
    }
}

J'ai éplucher tous le WEB openclassroom etc... pour voir si je faisait les chose bien.

Alors je fait peut être mal la requête mai j'ai bien mon message qui dit que l'update a bien étais effectuer et ma redirection, cependant rien ne change

Par contre si je la fait comme cela :

if(isset($_GET'id'])){
            $id = $db->quote($_GET'id']);
            $select = $db->prepare("UPDATE users SET avatar=$avatar, username=$username, slug=$slug, activation=$activation WHERE id=$id");
            $select->execute(array
                (
                    'avatar'=>$avatar, 
                    'username'=>$username, 
                    'slug'=>$slug, 
                    'activation'=>$activation
                )
            );
        }

Alors la tout fonctionne correctement mai je ne vois pas l'intérêt des requêtes préparé si j'utilise quand même des variables, je ne vois pas où je fait des conneries car j'ai fait ma requête inscription de la façon plus haut et elle rentre bien en BDD nos problèmes donc je suis paumé.

Pouvez svp sniper ce code et m'indiquer une quelconque erreur ce serai sympa :)

11 réponses


Carouge10
Réponse acceptée

Quand la variable est un string, oui.
Pour du numérique, vous pouvez tester avec la fonction is_numeric($ma_variable); qui retourne un booléan.

Bonsoir,

Un ID est une valeur numérique et non alphanumérique donc il ne faut pas lui mettre de '
Remplacer :

$id = $db->quote($_GET'id']);

par :

$id = $_GET'id'];

Quelle est l'intérêt du code suivant :

$id = $db->quote($_GET'id']);
        if(isset($_GET'id'])){
            $id = $db->quote($_GET'id']);

Inutile de récupérer l'id puis de tester son existence et s'il existe, on le récupère à nouveau.

De plus dans la requête préparer vous demander 5 éléments et vous en apporter que 4 dans le execute.
Ceci serait plus correcte:

$select = $db->prepare("UPDATE users SET avatar=:avatar, username=:username, slug=:slug, activation=:activation WHERE id=:id");
       $select->execute(array
                (
                    ':avatar'=>$avatar, 
                    ':username'=>$username, 
                    ':slug'=>$slug, 
                    ':activation'=>$activation,
                    ':id' => $id
                )
            );
neecride
Auteur

Merci de votre réponse !

Entre temps j'ai tester ce code pour une modification d'article :

if(isset($_POST'name']) && isset($_POST'slug'])){
    checkCsrf();
    $slug = $_POST'slug'];
    if(preg_match('/^[a-z\-0-9]+$/', $slug)){
        $name = $_POST'name'];
        $slug = $_POST'slug'];
        $category_id = $_POST'category_id'];
        $content = $_POST'content'];
        $description = $_POST'description'];    
    /**
        * update de la réalisation si on a un id en get
        **/
        if(isset($_GET'id'])){
                $u = array
                (
                    'id'=>$_GET'id'],
                    'category_id'=>$category_id, 
                    'name'=>$name, 
                    'slug'=>$slug, 
                    'content'=>$content, 
                    'description'=>$description
                );
            $sql = 'UPDATE works SET name=:name, slug=:slug, content=:content, description=:description, category_id=:category_id WHERE id=:id';
            $req = $db->prepare($sql);
            $req->execute($u);
    /**
        * insert de la réalisation si on a pas d'id en get
        **/ 
        }else{
            $q = array
                (
                    'category_id'=>$category_id, 
                    'name'=>$name, 
                    'slug'=>$slug, 
                    'content'=>$content, 
                    'description'=>$description
                );
            $sql = 'INSERT INTO works SET name=:name, slug=:slug, content=:content, description=:description, category_id=:category_id';
            $req = $db->prepare($sql);
            $req->execute($q);
            $_GET'id'] = $db->lastInsertId();
        }setFlash('La réalisation a bien été ajoutée !');

En gros j'ai tous supprimé les quote()

//au lieu de ça
$name = $db->quote($_POST'name']);
// j'ai mis ça la place
$name = $_POST"name"];

Apparemment ça beugué de là car j'ai refait les requêtes et elle s'enregistre bien l'update aussi je comprend pas je ne dois pas les protéger les $_POST ?

Salut,

Carouge10 que veux tu dire par protéger les variables ? avec les requêtes préparé sur PDO ça ne protège pas déjà automatiquement contre les injections SQL ?

Sinon je ne sais pas comment tu as config PDO lors de la création de l'objet mais je te conseil de mettre le mode d'erreur qui lève des exceptions puis de capturer les exceptions quand tu utilises la méthode execute.

Voici un exemple :

$sql =<<<EOD
    SELECT *
    FROM age
EOD;
    $req = $PDO -> prepare ($sql);
    try {
        $req -> execute();
    }
    catch (PDOException $e) {
        die ("Erreur de lecture dans la base de donnée: ".$e);
    }

De cette façon en cas d'erreur le script va s'arrêter et directement afficher l'erreur que renvoie mysql, utile pour rapidement savoir si la requête est correct et pour la production il vaut mieux que l'utilisateur voit une erreur plutôt qu'une page chargée mais buguée.

neecride
Auteur

Bonjour,

@Wapaca : donc si en faisant comme cela :

if(isset($_GET'id'])){
            $u = array
                (
                    'id'=>$_GET'id'],
                    'avatar'=>$avatar, 
                    'username'=>$username, 
                    'slug'=>$slug, 
                    'activation'=>$activation
                );
            $sql = 'UPDATE nimportquoi SET avatar=:avatar, username=:username, slug=:slug, activation=:activation WHERE id=:id';
            $req = $db -> prepare ($sql);
            try {
                $req -> execute($u);
                }
            catch (Exception $e) {
                echo 'La req a échoué';
                echo $e->getMessage();
                die();
            }   

        }

si echo ne me retourne pas le message alors la requête est bonne c'est le but du try ! mai j'ai mis n'import quoi dans la req et je n'ai pas de retour du echo.

Pour répondre a carouge10 les

$id = $db->quote($_GET'id']);

ça vient du tuto de grafikart quand je voulais me mettre a PDO j'ai regarder son tuto je pensée que c'étais bien puisse qu'il le faisait !

Alors si je reprend sur la sécu es-ce-que avec prepare c'est utile de faire ça ?

$username = htmlentities(addslashes($_POST'username'],ENT_QUOTES));
$avatar = htmlentities(addslashes($_POST'avatar'],ENT_QUOTES));
$activation = is_numeric($_POST'activation']);
$slug = htmlentities(addslashes($_POST'slug'],ENT_QUOTES));

Si ça ne sert a rien tant mieux.

Bonsoir,

@Wapaca : Il ne faut pas confondre injections sql et protections des variables
La protections des variables consistent à échappés les caractères spéciaux ( ", '...)

Pour les try catch, si pas d'écho alors la requête c'est bien passé.

@Carouge10 : Protection contre quoi ? les failles XSS ?

Non du tout, juste à éviter qu'une partie de la chaîne caractère ne soit coupé à cause d'un " ou d'un ' lors de son insertion dans la bdd.

neecride
Auteur

Bonjours,

Merci de vos réponse !

Pouvez vous m'éclairé sur une chose ?

Je souhaite me lancer dans la création d'un forum et je voudrai savoir comment joindre des tables ensembles et affiché le contenue de mes deux table dans le même foreach

J'ai vue pour faire comme ça :

$forum_cat = $db->query("SELECT forum_categories.id, forum_categories.name, forum_categories.date, forum_categories.ordre FROM forum_categories LEFT JOIN forums ON forums.id=forum_categories.id ORDER BY ordre ASC")->fetchAll();

Mai quand je veut afficher le titre du forum et sa description liée a l'id de forum_categories ça ne fonctionne pas je ne vois pas comment faire une jointure en affichant le contenue des deux tables.

Pouvez vous m'aidez sur ce point je suis largué !

D'avance merci !

Bonsoir,

C'est un autre sujet, donc un autre topic.
Si celui-ci est résolu merci de le notifier.

Pour les jointures, cela concerne le SQL, il vous faut remettre un sujet dans cette partie du forum.

Merci.

neecride
Auteur

A oui désolé Carouge