Bonjour bonjour,

Je suis en train de mettre en place un formulaire d'inscription à étapes sur l'idée du tuto de grafikart "Cakephp - Systeme membres" mais sur la base du tuto MVC.
Voila les étapes principales
Etape 1 : Inscription basique (nom, email, adresse ...)
Etape 2 : Envoi du mail avec lien d'activation du compte et voila le probleme

Je reçois bien le mail, le lien d'activation est bien généré, je demande qu'au clic sur le lien le champ active passe de 0 à 1 et là BOUM !
La fonction ne fait pas un update mais un insert et je me retrouve avec un enregistrement supplémentaire avec tout les champs vides SAUF active qui lui est à 1.

Voila le code de la fonction activate, si quelqu'un peut me sauver ! S'il vous plait !! :)

function activate($token) {
    $this->loadModel('Profil');
    $token = explode('-', $token);

    $user = $this->Profil->findFirst(array(
        'conditions' => array('id' => $token[0],'MD5(Profil.password)' => $token[1],'active' => 0)
    ));

        if(!empty($user))
        {
            $this->Profil->id = $user->id;
            $this->Profil->save(array('active' => 1));

            $this->Session->setFlash('Votre compte a bien été activé, nous pouvons continuer. '.$this->Profil->id); 
            $this->redirect('profils/spec/'.$token[0]); 
        }
        else 
        {
            $this->Session->setFlash('Désolé, mais ce lien d\'activation n\'est pas valide.','error'); 
        }
    }

9 réponses


Tackacoder
Réponse acceptée

Je pense qu'en fait le paramètre envoyé à save() doit-être un objet et non un tableau
Edit: Ton erreur est dû au fait que ton $fields et $d n'ont pas le même nombre d'éléments, ou un truc du genre

FannyM
Auteur
Réponse acceptée

Bien vu !!! C'était ça il voulait un objet ! Du coup, voila ce que donne la fonction activate :

function activate($token) {
        $this->loadModel('Profil');
        $token = explode('-', $token);

        $this->request->data = $this->Profil->findFirst(array(
                'conditions' => array('id' => $token[0],'MD5(Profil.password)' => $token[1],'active' => 0)
            ));

        if(!empty($this->request->data))
        {
            $this->request->data->active = 1;
            $this->Profil->save($this->request->data);

            $this->Session->setFlash('Votre compte a bien été activé, nous pouvons continuer. '.$this->Profil->id); 
            $this->redirect('profils/spec/'.$token[0]); 
        }
        else 
        {
            $this->Session->setFlash('Désolé, mais ce lien d\'activation n\'est pas valide.','error'); 
        }
    }

Je dirais presque que c'était évident, mais je suis resté focalisé sur un truc et forcément ... Merci exothermique ! :D

Bonsoir,
je pense qu il tu faut creer une fonction update dans ton model et remplacer
" $this->Profil->save(array('active' => 1)); " par
" $this->Profil->update(array('active' => 1)); "
si ma comprehension est bonne "save" sert a enregistrer un enregistrement dans la base de donnees alors que update devrais modifier un enregistrement existant dans la base de donnees

je pense que je viens de dire de grosse betise.... un peu fatigué ce soir;
ne devrais tu pas donner plus de renseignement dans ton tableau
" $this->Profil->save(array('active' => 1)); "
la tu lui demande de sauvegarder un tableau avec la cle = active et la valeur = 1
mais tu ne lui fournis pas de condition pour aller sur tel enregistrement deja existant
de ce fait il cree un nouvel enregistrement

FannyM
Auteur

Hello, merci de répondre ^^

Voici la fonction save dans le Model.php :

public function save($data){
        $key = $this->primaryKey;
        $fields = array();
        $d = array(); 
        foreach($data as $k=>$v){
            if($k!=$this->primaryKey){
                $fields] = "$k=:$k";
                $d":$k"] = $v; 
            }elseif(!empty($v)){
                $d":$k"] = $v; 
            }
        }
        if(isset($data->$key) && !empty($data->$key)){
            $sql = 'UPDATE '.$this->table.' SET '.implode(',',$fields).' WHERE '.$key.'=:'.$key;
            $this->id = $data->$key; 
            $action = 'update';
        } 
        else
        {
            $sql = 'INSERT INTO '.$this->table.' SET '.implode(',',$fields);
            $action = 'insert'; 
        }

        $pre = $this->db->prepare($sql); 
        $pre->execute($d);

        if($action == 'insert'){
            $this->id = $this->db->lastInsertId(); 
        }
    }

Comme on peut le voir elle peut faire un insert ou un update, habituellement je rentre en paramètre $this->request->data mais là je ne vois pas trop quoi lui passer en paramètre pour qu'elle fasse un update.

Bonjour,
En fait, la fonction save() vérifie si dans le tableau passé en paramètre, il existe une clé primaire. Et selon ce test effectue un INSERT ou un UPDATE.

$this->Profil->save(array('id' => $user->id,'active' => 1));
FannyM
Auteur

Hello exothermique,

J'ai essayé ta solution et il me dit des mots doux de ce genre là :

Warning: PDOStatement::execute() [pdostatement.execute]: SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens in /home/studiomk/www/core/Model.php on line 212
Warning: PDOStatement::execute() [pdostatement.execute]: SQLSTATE[HY093]: Invalid parameter number in /home/studiomk/www/core/Model.php on line 212

Sachant que la ligne 212 c'est

$pre->execute($d);

et quand je fais un debug de $sql => la requete c'est : INSERT INTO profils SET active=:active

Bonjour,
en sql pour un insert : INSERT INTO nomtable (nomchamp1text, nomchamp2numeric, nomchamp3date)
VALUES ('valeurchamp1', valeurchamp2, 'valeurchamp3')

en sql pour un Update : UPDATE "nom de table" SET "colonne 1" = [nouvelle valeur] WHERE {condition}

"et quand je fais un debug de $sql => la requete c'est : INSERT INTO profils SET active=:active"

la je pense que tu vois mieux ton problème....

cela fonctionne si id est déclarer mais comment lui dire que "id" s'appel autrement ?