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 Discussion :

tuto ferme du web: Invalid parameter number: number of bound variables does not match number of tokens [1.x]


Sujet :

PHP

  1. #1
    Membre régulier
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2008
    Messages
    207
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

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

    Informations forums :
    Inscription : Février 2008
    Messages : 207
    Points : 114
    Points
    114
    Par défaut tuto ferme du web: Invalid parameter number: number of bound variables does not match number of tokens
    Bonjour,

    Je suis en train de terminer le tuto de la ferme du web (oui, je sais, il est sous symfony 1.2, mais je l'ai adapté pour sf 1.4)

    Je rencontre cependant un problème avec leur principe d'authentification (je sais qu'ils ont réinventé la roue car il existe des plugins pour)

    J'ai le routing suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    login_donateur:
      url: /don/login
      param: { module: donateur, action: login }
     
    check_login_donateur:
      url: /don/verification-mot-de-passe
      param: { module: donateur, action: doLogin }
    Quand je veux m'authentifier, la route suivie est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    login_donateur:
      url: /don/login
      param: { module: donateur, action: login }
    et le code de l'action:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public function executeLogin(sfWebRequest $request)
        {
            $this->form = new LoginForm();
        }
    Voici la classe du formulaire:
    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
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    <?php
     
    class LoginForm extends sfForm
    {
     
        public function configure()
        {
     
            unset(
                    $this["lvl"], $this["etat"], $this["id"], $this["ip_inscription"], $this["last_login"], $this["date_inscription"]
            );
     
            $this->setWidgets(array(
                'login' => new sfWidgetFormInputText(),
                'pass' => new sfWidgetFormInputPassword()
            ));
     
            $this->widgetSchema->setNameFormat('login[%s]');
     
            $this->setValidators(array(
                'login' => new sfValidatorAnd(
                        array(
                            new sfValidatorString(
                                    array('required' => true, 'min_length' => 3, 'max_length' => 14),
                                    array(
                                        'min_length' => "L'identifiant est trop court. 3 caractères minimum.",
                                        'max_length' => "L'identifiant est trop long. 14 caractères maximum",
                                    )
                            ),
                            new sfValidatorRegex(
                                    array('pattern' => '/^[a-zA-Z0-9-]+$/')
                            )
                        ),
                        array(),
                        array(
                            'required' => "L'identifiant est indispensable",
                            'invalid' => "L'identifiant ne peut contenir de caractères spéciaux."
                        )
                ),
                'pass' => new sfValidatorString(
                        array('required' => true, 'min_length' => 6, 'max_length' => 20),
                        array(
                            'min_length' => "Le mot de passe est trop court. 6 caractères minimum.",
                            'max_length' => "Le mot de passe est trop long. 20 caractères maximum",
                            'required' => "Le mot de passe est indispensable",
                            'invalid' => "Le mot de passe doit avoir entre 6 and 20 caractères"
                        )
                ),
            ));
     
            $this->validatorSchema->setPostValidator(
                    new sfValidatorCallback(array('callback' => array($this, 'checkLogin')))
            );
        }
     
        public function checkLogin($validator, $values)
        {
     
            if (!empty($values['login']) && !empty($values['pass']))
            {
     
                $membre = Doctrine::getTable('donateur')->findOneByLogin($values['login']);
     
                if ($membre)
                {
     
                    if ($membre->getPass() == ($values['pass']))
                    {
                        // Login correct !
     
                        if ($membre->getEtat() == 1)
                        {
     
                            return $values;
                        }
                        else
                        {
                            if ($membre->getEtat() == 0)
                            {
                                throw new sfValidatorError($validator, 'Votre compte est toujours désactivé. Veuillez cliquer sur le lien de confirmation reçu par mail pour activer votre compte.');
                            }
                            else
                            {
                                throw new sfValidatorError($validator, 'Vous êtes banni du site.');
                            }
                        }
                    }
                    else
                    {
                        // Connexion incorrecte
                        throw new sfValidatorError($validator, 'L\'identifiant et/ou le mot de passe est incorrect');
                    }
                }
                else
                {
                    throw new sfValidatorError($validator, 'L\'identifiant n\'existe pas.');
                }
            }
        }
     
    }
    Le code d'affichage de ce formulaire est le suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <h2>Connexion</h2>
     
    <form action="<?php echo url_for('@check_login_donateur'); ?>" method="post">
        <table>
            <?php echo $form; ?>
            <tr>
                <td colspan="2"><input type='submit' value="Connexion" /></td>
            </tr>
        </table>
    </form>
    A ce moment-là, c'est ce code, dans actions.class.php, qui s'exécute:
    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
        public function executeDoLogin(sfWebRequest $request)
        {
            $this->forward404Unless($request->isMethod('post'));
     
            $this->form = new LoginForm();
     
            $this->form->bind($request->getPostParameter('login'));
     
            if ($this->form->isValid())
            {
                $donateur = Doctrine::getTable('donateur')
                        ->findOneByLogin($request->getPostParameter('login'));
     
                // On set la session de l'utilisateur.
                $this->getUser()->setAuthenticated(true);
     
                // On stocke les infos utiles dans la session utilisateur
                $this->getUser()->setAttribute("id", $donateur->getId());
                $this->getUser()->setAttribute("login", $donateur->getLogin());
                $this->getUser()->setAttribute("level", $donateur->getLvl());
     
                // On set les accès de l'utilisateur
                switch ($donateur->getLvl())
                {
                    case 1:
                        $this->getUser()->addCredential("donateur");
                        break;
                    case 9:
                        $this->getUser()->addCredential("admin");
                        break;
                    default:
                        $this->getUser()->addCredential("donateur");
                }
     
                $this->redirect('@homepage');
            }
            else
            {
                $this->setTemplate("login");
            }
        }
    J'ai cru que l'erreur venait du fait que le mot de passe semblait ne pas être bindé avec le formulaire ici:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     $this->form->bind($request->getPostParameter('login'));
    dans executeDoLogin()

    J'ai donc écrit ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     $this->form->bind($request->getPostParameter('login'), getPostParameter('pass'));
    Quand je soumets le formulaire avec un login et un mot de passe, j'obtiens l'erreur suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens
    A la place de membres, j'ai donateurs dans mon schema, mais ça ne change rien:
    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
    donateur:
      columns:
        civilite_id:
          type: integer(20)
          notnull: true
        login: 
          type: string(45)
          notnull: true
        pass: 
          type: string(45)
          notnull: true
        first_name: 
          type: string(255)
          notnull: true
        last_name: 
          type: string(255)
          notnull: true
        email:
          type: string(255)
          notnull: true
          unique: true
        raison_sociale:
          type: string(255)
          default: null
        address:
          type: string(255)
          notnull: true
        postal_code:
          type: integer(5)
          notnull: true
        town:
          type: string(255)
          notnull: true
        country:
          type: string(2)
          notnull: true
        date_inscription:
          type: timestamp
          default: null
        ip_inscription:
          type: string(16)
          default: null
        last_login:
          type: timestamp
          default: null
        lvl:
          type: integer(4)
          default: null
        etat:
          type: integer(4)
          default: null
    J'ai beau chercher depuis hier, je ne vois pas le problème.

    Quelqu'un qui a réalisé ce tutoriel ou qui a déjà connu ce genre de problème pourrait-il m'aider à y voir plus clair?

    Merci par avance,
    Johnny3

  2. #2
    Membre régulier
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2008
    Messages
    207
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

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

    Informations forums :
    Inscription : Février 2008
    Messages : 207
    Points : 114
    Points
    114
    Par défaut
    En continuant à chercher, je me suis rendu compte que le problème venait de cette requête:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $donateur = Doctrine::getTable('donateur')
                        ->findOneByLogin($request->getPostParameter('login'));
    sans que je sache pourquoi.

    Du coup, j'ai tenté ceci, qui a fonctionné:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    public function getDonateurByLoginAndPass($login, $pass)
        {
            return $this->createQuery('c')
                    ->andWhere('c.login = ?', $login)
                    ->andWhere('c.pass = ?', md5($pass));
        }
    dans donateurTable.class.php, et j'ai remplacé le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $donateur = Doctrine::getTable('donateur')
                        ->findOneByLogin($request->getPostParameter('login'));
    par celui-ci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $donateur = Doctrine::getTable('donateur')
                        ->getDonateurByLoginAndPass($request->getPostParameter('login'), $request->getPostParameter('pass'));
    Ca a fonctionné, mais maintenant, j'ai une autre erreur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Fatal error: Call to undefined method Doctrine_Query::getId() in /Users/johnny3/Sites/mes_projets_symfony/lfsm/apps/frontend/modules/donateur/actions/actions.class.php on line 145
    Le problème vient de ces lignes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    $this->getUser()->setAttribute("id", $donateur->getId());
    $this->getUser()->setAttribute("login", $donateur->getLogin());
    $this->getUser()->setAttribute("level", $donateur->getLvl());
    Je ne vois pas où est l'erreur, car la notation semble correcte.

    Une idée?

  3. #3
    Membre habitué Avatar de Maerlyn31
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2011
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mai 2011
    Messages : 71
    Points : 167
    Points
    167
    Par défaut
    Ta méthode getDonateurByLoginAndPass, étant donné qu'elle ne contient pas de ->execute(); renvoie une Doctrine_Query, et non un Donateur.

    Remplace ta méthode par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    public function getDonateurByLoginAndPass($login, $pass)
        {
            return $this->createQuery('c')
                    ->andWhere('c.login = ?', $login)
                    ->andWhere('c.pass = ?', md5($pass))
                    ->execute();
        }
    ou bien dans ton action son appel par :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $donateur = Doctrine::getTable('donateur')
                        ->getDonateurByLoginAndPass($request->getPostParameter('login'), $request->getPostParameter('pass'))
                        ->execute();
    ça devrait déjà aller mieux

  4. #4
    Membre régulier
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2008
    Messages
    207
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

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

    Informations forums :
    Inscription : Février 2008
    Messages : 207
    Points : 114
    Points
    114
    Par défaut
    Bonjour Maerlyn31,

    Merci pour ta réponse. Quelle erreur stupide!

    J'ai mis ->execute() dans la requête de donateurTable.class.php et... poum, la même erreur qu'au départ!
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens
    C'est étrange, non? Je fais uniquement une requête SELECT, pourquoi ai-je un message comme si j'essayais de faire un INSERT ou un UPDATE avec un nombre de champ ne correspondant pas à la requête?

    En tout cas, le reste du code fonctionne, car si , pour tester, je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
                $donateur = Doctrine::getTable('donateur')
                        ->find(1)
    uniquement pour retrouver mon premier donateur, ça fonctionne et je vois bien, dans la barre de debug, avec User, que je suis authentifié et que les bonnes infos sont dans la session.

    Je continue de chercher...

  5. #5
    Membre habitué Avatar de Maerlyn31
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2011
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mai 2011
    Messages : 71
    Points : 167
    Points
    167
    Par défaut
    Une chose m'étonne aussi dans ton code, sur l'usage que tu fais de la fonction bind().
    Grace à la ligne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $this->widgetSchema->setNameFormat('login[%s]');
    dans ton formulaire, tes champs doivent être nommés login[login] et login[pass]. Il suffit donc d'un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bind($request->getParameter('login'))
    Pour lier les deux champs de formulaire.

    Sinon, dans la web debug toolbar tu dois pouvoir visualiser les requêtes SQL passées (l'onglet le plus à droite). Ca pourra peut être aider au debugging

  6. #6
    Membre régulier
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2008
    Messages
    207
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

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

    Informations forums :
    Inscription : Février 2008
    Messages : 207
    Points : 114
    Points
    114
    Par défaut
    Citation Envoyé par Maerlyn31 Voir le message
    Une chose m'étonne aussi dans ton code, sur l'usage que tu fais de la fonction bind().
    Grace à la ligne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $this->widgetSchema->setNameFormat('login[%s]');
    dans ton formulaire, tes champs doivent être nommés login[login] et login[pass]. Il suffit donc d'un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bind($request->getParameter('login'))
    Pour lier les deux champs de formulaire.

    Sinon, dans la web debug toolbar tu dois pouvoir visualiser les requêtes SQL passées (l'onglet le plus à droite). Ca pourra peut être aider au debugging
    Tu viens de m'expliquer quelque chose que je n'avais jamais compris. Je pensais qu'on devait faire un bind de chaque paramètre. Dans le tuto de la ferme du web, ils avaient bien fait comme tu as dit, à savoir
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $this->form->bind($request->getParameter('login'));
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $donateur = Doctrine::getTable('donateur')->findOneByLogin($request->getParameter('login[login]'));
    mais curieusement, dans la debugbar, symfony dit qu'il n'y a aucune valeur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    at donateurTable->findOneByLogin(null)
    Comment se fait-il que $request->getParameter('login[login]' renvoie une valeur nulle?

    Alors que si, pour tester, comme tout à l'heure, je tape directement le login d'un donateur en faisant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $donateur = Doctrine::getTable('donateur')->findOneByLogin('johnny3'));
    , ça fonctionne.

    Le problème vient donc de là. Je vais voir si c'est une question de post en utilisant getPostParameter au lieu de getParameter

  7. #7
    Membre régulier
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2008
    Messages
    207
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

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

    Informations forums :
    Inscription : Février 2008
    Messages : 207
    Points : 114
    Points
    114
    Par défaut
    C'était ça!

    Il fallait écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $donateur = Doctrine::getTable('donateur')
                        ->findOneByLogin($request->getPostParameter('login[login]'));
    et non pas
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $donateur = Doctrine::getTable('donateur')
                        ->findOneByLogin($request->getParameter('login[login]'));
    Bon sang que c'était idiot comme erreur, mais j'ai été perturbé par le fait que l'on puisse faire un bind sur une requête en POST avec un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $this->form->bind($request->getParameter('login'));
    au lieu de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $this->form->bind($request->getPostParameter('login'));
    Bon, j'espère que ça aidera ceux qui ont galéré comme moi sur ce genre de problème. Merci!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Number of records does not match index
    Par sniperpro dans le forum Paradox
    Réponses: 10
    Dernier message: 08/12/2010, 15h28
  2. Réponses: 6
    Dernier message: 03/06/2010, 10h09
  3. [MySQL] Number of bound variables does not match number of tokens
    Par grenoult dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 09/04/2010, 09h18
  4. Réponses: 3
    Dernier message: 25/08/2009, 23h25
  5. Réponses: 1
    Dernier message: 10/05/2006, 12h11

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