0

I'm working on a program to update the user's password with PHP/MySQL. The table is titled 'utilisateurs' and contains several fields:

• numero (auto-increment);

• identifiant (user ID);

• motdepasse (password).

The user has to provide the actual password ($ancienmdp) and to type the new password twice ($nouveaumdp1 and $nouveaumdp2) and then submit the form.

Here's the part of program I'm working on and for which, despite my investigations, I still haven't found any solution:

//On récupère le mot de passe actuel et les deux nouveaux mots de passe entrés par l'utilisateur.
        $ancienmdp = $_POST['ancienmdp'];
        $nouveaumdp1 = $_POST['nouveaumdp1'];
        $nouveaumdp2 = $_POST['nouveaumdp2'];
        
        
        if ($nouveaumdp1 != $nouveaumdp2) { //Si les deux nouveaux mots de passe ne correspondent pas...
                
            //... un message d'erreur s'affiche pour indiquer que les deux nouveaux mots de passe ne correspondent pas.
            $message = '<p class="normal">Le nouveau mot de passe et sa confirmation ne correspondent pas ! Veuillez taper à nouveau votre nouveau mot de passe.</p>';
            
        } else { //Si les deux nouveaux mots de passe correspondent...
            
            //On recherche le mot de passe actuel de l'utilisateur.
            $identifiantrecherche = $_SESSION['identifiant'];
            
            $q= $dbco->prepare("SELECT motdepasse FROM `utilisateurs` WHERE identifiant=?");
            $q->execute([$identifiantrecherche]);
            $actuelmdp = $q->fetchColumn();
            
            if ($ancienmdp != $actuelmdp) { //Si le mot de passe actuel entré ne correspond pas à celui déjà enregistré...
                
                //... un message d'erreur indique que le mot de passe actuel n'est pas valide.
                $message = '<p class="normal">Mot de passe actuel invalide ! Veuillez taper à nouveau vos actuel et nouveau mots de passe.</p>';

                
            } else { //S'ils correspondent bien...
                
                
                //... on met à jour le mot de passe de l'utilisateur...
                $sth = $dbco->prepare("UPDATE `utilisateurs` SET `motdepasse` = :nouveaumdp1 WHERE `identifiant` = :identifiantrecherche");
                
                //echo '$identifiant = ' . $identifiantrecherche . ' ; $motdepasse = ' . $nouveaumdp1;
                
                $sth->bindParam(':identifiant',$identifiantrecherche, PDO::PARAM_STR);
                $sth->bindParam(':motdepasse',$nouveaumdp1, PDO::PARAM_STR);
                $sth->execute();
                //... et on indique à ce dernier que son mot de passe a bien été modifié.
                $message = '<p class="normal">Mot de passe modifié !</p>';
            } }

I get the error:

'Erreur !: SQLSTATE[HY093]: Invalid parameter number: parameter was not defined'

The 'motdepasse' field has to be updated and the 'identifiant' field is used to find the right user. So, I use bindParam for these two fields.

What am I doing wrong?

Thanks!

Paul T.
  • 4,703
  • 11
  • 25
  • 29
  • 1
    Well you've found how to do this "somewhere" but what is interesting is you are performing two queries completely differently... Compare your first query to your second one and see what you can see that's different. – TimBrownlaw Jul 28 '22 at 23:08
  • 1
    The query contains placeholders `:nouveaumdp1` and `:identifiantrecherche`. You need to use the same strings in the calls to `bindParam()`. – Barmar Jul 28 '22 at 23:27
  • @TimBrownlaw Thanks for your reply! Indeed, the first query fetches directly the actual password with positional placeholders and not with named placeholders. I didn't know the two queries had to be stated the same way! I'll write the answer below. Thanks again! – Fabien Nguyen Jul 29 '22 at 07:45
  • @Barmar Thanks for your reply. The problem wasn't on the placeholder names, but on the query type. The answer is now below. – Fabien Nguyen Jul 29 '22 at 07:47
  • You can use named placeholder, I strongly recommend them. You just have to be consistent and use the same names when you call `bindParam()`, or use an associative array with the same names if you pass the parameters in the call to `execute()`. – Barmar Jul 29 '22 at 17:26

2 Answers2

0

Thanks to @TimBrownlaw, I stated the second query with positional placeholders like the first query is, and not with named placeholders as I did.

The second query becomes:

$sth = $dbco->prepare("UPDATE `utilisateurs` SET motdepasse=? WHERE identifiant=?");
                
$sth->execute([$nouveaumdp1,$identifiantrecherche]);

Now it works!

Thanks for your help and your time!

0

The placeholders in bindParam() need to match the placeholders in the query.

$sth->bindParam(':identifiantrecherche',$identifiantrecherche, PDO::PARAM_STR);
$sth->bindParam(':nouveaumdp1',$nouveaumdp1, PDO::PARAM_STR);
Barmar
  • 741,623
  • 53
  • 500
  • 612