Bonsoir,

Je cherche à faire un formulaire à l'aide de $validate afin de contrôler les infos du visiteur avant l'envoi, cependant je n'arrive pas à rendre certains champs obligatoires.

J'aimerais que les champs "password", "done" et "gender" soient obligatoires, cependant je ne trouve pas ce qui permet de le faire dans la documentation. :/

De plus, je cherche à ce que l'utilisateur entre un password et une adresse mail de validations, comment faire? Uiliser beforeSave dans le model?

Voilà côté code :

//register.ctp (view)
<h2>Register</h2>
<?php
echo $form->create('User', array('url' => array('action' => 'register')));
echo $form->input("username", array("label" => "Login : ", "value" => ""));
echo $form->input("password", array("label" => "Password : ", "value" => ""));
//echo $form->input("password", array("label" => "Password confirm : ", "value" => ""));
echo $form->input("email", array("label" => "Email adress : ", "value" => ""));
//echo $form->input("email", array("label" => "Email confirm : ", "value" => ""));
echo "<label>Gender : </label>" . $this->Form->select('sex', array("M" => "Male", "F" => "Female"));
echo "<br /> <br />";
echo $this->Form->checkbox("done") . "<p style='display: inline;'> I accept the <a href='" . $this->Html->url(array('controller' => 'pages', 'action' => 'rules')) ."' target='_blank'>General Terms</a></p>";
echo "<br /><br />";
echo $form->end("Register");
?>

//user.php (model)
<?php
class User extends AppModel {
    var $name = 'User';

    var $validate = array(
        "email" => "email",

        "username" => array(
            "alphaNumeric" => array(
                "rule" => "alphaNumeric",
                "required" => true,
                "message" => "You must use alphanumeric characters only",
            ),
            "between" => array(
                "rule" => array("between", "4", "15"),
                "message" => "Your login must contains between 4 and 15 characters",
            ),
            "isUnique" => array(
                "rule" => "isUnique",
                "message" => "Your login has already been taken"
            ),
        ),
        "password" => array(
            "rule" => "notEmpty",
            "message" => "Your password is required",
        ),

        "gender" => array(
            "rule" => array("multiple"),
            "message" => "You must specify a gender",
        ),

        "done" => array(
            "rule" => array("equalTo", 1),
            "message" => "You must accept the general terms",
        ),
    );

    //function beforeSave() {
        /*$this->data"User"]"password"] = Security::hash($this->data"User"]"password"], null, true);
        return true;*/
    //}
}
?>

//users_controller.php (controller)
function register() {
        if($this->Session->read("Auth.User.id"))
        {
            $this->redirect("/");
        } else {
            if (isset($this->data)) {
                $this->User->set($this->data);
                if($this->User->validates())
                {
                    $this->User->save($this->data);
                    $this->flash('Register successful! Click to continue','/');
                } else {
                    $this->Session->setFlash("Error!");
                }
            }
        }

        $this->layout = "archives_default";
    }

Savez-vous comment faire? Merci !

15 réponses


Flohw
Réponse acceptée

le vidage de champs, c'est parce que tu as, dans les options de la création du champ 'value' => ''
pour le mot de passe, je ne vois pas pourquoi il y a le message, mauvaise appellation du champs dans le fomulaire ou dans le modele (variable de validation) sans doute.
pour vérifier que le select soit correct, c'est bien la regle multiple qu'il faut utiliser mais re-regarde la doc (et fait attention, dans le modele tu as 'gender' => array(...) et dans le fomulaire, c'est 'sex'
et pour la checkbox, si elle est cochée la variable vaut 1 donc tu peux vérifier avec equalTo (cf la doc aussi) si elle n'est pas oligé d'etre cochée, tu peux vérifier soit avec multiple soit isNumeric (plus large)

Flohw
Réponse acceptée

pour le done, essaye sans les guillements au tour du 1 apres equalTo et pour le mot de passe, utilise la technique que je t'ai donnée : regle de validation personnelle, avec la condition $chek'password'] != $this->Auth->password(''), $check etant un parametre de ta fonction, obligatoir (ou quasiment, cf doc). je ne sais pour quelle raison le notEmpty n'a jamais marché pour moi sans doute parce que le mot de passe est hashé avant la vérification (ce qui n'est effectivement pas une bonne idée de la part de Cake :-°)
pour ton beforeSave, oublie c'est pas dans ce callback que tu auras la solution parce que c'est ce qui est executé juste apres que tu ais appelé la méthode $this->User->save() donc une fois que toutes les données aient été traitées (et oublie toutes les methodes de callback sur cette application sauf peut etre beforeValidate mais absolument pas sur)

il faut que tu ajoutes dans le alphaNumeric de name la valeur 'allowEmpty' => false
pour le mot de passe, ajoute 'required' => true, 'allowEmpty' => false (mais c'est pas sur que ca marche parce que je crois qu'il crypte le mdp avant d'appliquer les règles donc il faut que tu fasses une règle de validation perso et que tu vérifies si la valeur crypte est égale ou non au mot de passe vide crypté
pour les autres, c'est pareil : ajoute 'required' et 'allowEmpty'
pour les champs de vérification (email et pwd) ajoute un champ dans la vue et dans le modele, ajoute la règle pour ce champ avec une règle personalisée (fonction) qui vérifie le tout

voila, si c'est pas clair, demande parce que sur le dernier point j'ai pas eu l'impression d'etre super clair ^^

Zouox
Auteur

Merci !

Cependant je quand j'essaye ça pour le password :

<?php
       "password" => array(
            "required" => array(
                "required" => true,
                "message" => "Your password is required"
            )
        ),?>

Le message d'erreur persiste, même si le champs est complété. :S

Pour "gender" qui est un "select", je n'arrive pas à imposer un choix parmis les deux valeurs et pour le champs "done" qui est une "checkbox" je n'arrive pas à imposer la validation.

Edit : Aussi, comment faire en sorte que quand l'utilisateur se trompe dans la complétion des champs, les champs ne soit pas vidés (au chargement de la page)?

Pouvez-vous m'aider? Merci !

Dans ton form create() tu peux directement mettre "action"=>"register", l'url n'est pas nécessaire vu que tu ne change pas le controller

Pour ta règle met plutot

"password" => array(
    'rule' => 'notempty',
    'required' => true,
    'message' => 'blablabla'
)
Zouox
Auteur

Avant tout, merci pour vos réponses. :)

J'ai du mal avec la checkbox "done", pourtant, d'après la documentation elle devrait fonctionner. :s

Voilà le code (j'ai retiré ce qui fonctionne et commenté ce qui ne fonctionne pas) :

<?php
class User extends AppModel {
    var $name = 'User';

    var $validate = array(
        "password" => array(
            "rule" => "notEmpty", //le password est automatiquement haché, même si la chaîne de caractères est vide
            "required" => true,
            "message" => "Your password is required"
        ),

        "done" => array(
            "equalTo" => array(
                "rule" => array("equalTo", "1"), //si la checkbox n'est pas cochée, il n'y a pas de message d'erreur alors que le formulaire ne passe pas
                "required" => true,
                "message" => "You must accept the general terms"
            )
        ),
    );

    /*function beforeSave() {
        $this->data"User"]"password"] = Security::hash($this->data"User"]"password"], null, true);
        return true;
    }*/
}
?>

Savez-vous pourquoi ça ne fonctionne pas? Merci !

Autres questions : comment vérifier que de la chaîne de caractères "password" n'est pas vide avant qu'elle ne soit hachée? Dans un "beforeSave"? D'ailleurs, peut-on désactiver la hachage automatique du password afin de le faire nous même à la main dans le model User?

Merci de votre aide ! ;)

Zouox
Auteur

Merci pour ta réponse.

Pour le "done", même sans les guillemets cela ne fonctionne pas. :s

Pour le password, cela ne fonctionne pas avec ta condition (Undefined property: User::$Auth | Fatal error: Call to a member function password() on a non-object), j'ai donc essayé :

<?php function passwordIsNotEmpty($check) {
        if ($check"password"] != "") {
            return true;
        } else {
            return false;
        }
    } ?>

Mais la fonction retourne "true" même si le champs est vide. :/

Une idée ? Merci ! :)

oui pour le password :

App::import('Component', 'Auth');
$auth = new AuthComponent();
$auth->password('');
/*et la suite pareil*/

pour le done, j'ai pas d'idée par contre

Zouox
Auteur

Merci, donc de cette façon?

function passwordIsNotEmpty($check) {        
        App::import('Component', 'Auth');
        $auth = new AuthComponent();
        $auth->password("");

        if ($check'password'] != "") {
            return true;
        } else {
            return false;
        }
    }

Même si le champs est vide, il n'y a pas de message d'erreur. :s

oui maisc'est if ($check'password'] != $auth->password('')) ...

Zouox
Auteur

Ça marche parfaitement pour le password, merci bien ! ;)

Reste plus qu'à imposer le clic sur la checkbox, j'ai tout essayé, ' (equalTo, "1") ' et ' (equalTo, 1) ', la seule différence c'est qu'avec le int, le formulaire n'est pas possible à poster, mais aucun message d'erreur n'apparaît.. :s

Quelqu'un a une idée? Merci !

ha je viens de me souvenir que j'avais fait ce genre de chose :D
bon c'est peut etre pas hyper propre mais bon...

'done' => array('rule' => array('comparison', '==', 1)
'messsage' => 'ton message d'erreur'),

ca chez moi ca marche ;)

Zouox
Auteur

J'ai compris, en fait c'est dans la vue qu'il y a un problème, j'aurais dû utiliser :

<?php echo $form->input("done", array("label" => "", "type" => "checkbox"));?>

Tout bêtement, là il crée une div qui porte la bonne classe et le message d'erreur apparaît. ^^

Cependant, comment faire pour inclure un texte à côté de cette checkbox (à droite) dans le même div ?

Avec ce code :

<?php
echo $form->input("done", array("label" => "", "type" => "checkbox")) . "<p style='display: inline;'> I accept the <a href='" . $this->Html->url(array('controller' => 'pages', 'action' => 'rules')) ."' target='_blank'>General Terms</a></p>";
?>

Le texte est sous la div de la checkbox.

Et si je mets le texte dans le label, il sera automatiquement à gauche, en css est-il possible de faire en sorte que le label de la checkbox soit à droite?

Merci !

oui, c'est possible en css, tu peux aussi le mettre dans le 'after', c'est pas hyper propre non plus (par rapport au lable qu'on est censé pouvoir cliquer dessus pour activer/desactiver la case, c'est pour l'accessibilité) mais ca marche ;)

Zouox
Auteur

Finalement je l'ai mis dans le label, pour l'accessibilité. Merci beaucoup à vous ! ;)