8 Le formulaire d’inscription de WatchMyDesk
Cette partie va être assez compliquée et un peu longue. Accrochez vous !
Plan de l’épisode #08
- Création du formulaire d’inscription.
- Modification de l’apparence du formulaire
- Finitions du formulaire.
- Valider notre formulaire dans le controller
- Ajout du membre dans la base de donnée
- Email de validation
- Conclusion
Création du formulaire d’inscription.
Comme vous avez pu le voir, cette partie va être assez longue. Nous allons tout de suite attaquer par la création de l’objet Zend_Form de notre formulaire.Pour cela, nous avons besoin de savoir les champs à utiliser pour qu’un utilisateur puisse s’inscrire.
Quand un membre s’inscrira, il devra renseigner :
- Son Login ( Entre 3 et 15 caractères alphanumériques uniquement.)
- Son Email (Email valide)
- Son Password et la confirmation (Entre 6 et 20 caractères.)
- Le captcha (pour empêcher les robots de s’inscrire)
Un formulaire construit avec Zend_Form à une structure précise :
1.class Form_Inscription extends Zend_Form2.{3. public function __construct($options = null)4. {5. parent::__construct($options);6. // le formulaire7. }8.}Commençons par le champs Login. Celui-ci doit être unique dans la base de donnée (c’est à dire que deux personnes ne peuvent pas s’inscrire avec le même login). Il est obligatoire et entre 3 et 20 caractères.
01.class Form_Inscription extends Zend_Form02.{03. public function __construct($options = null)04. {05. parent::__construct($options);06. $login = new Zend_Form_Element_Text("login", array('size' => 25));07. $loginDoesntExist = new Zend_Validate_Db_NoRecordExists('membres', 'login');08. $login ->setLabel('Login')09. ->addFilter('StripTags')10. ->addFilter('StringTrim')11. ->addValidator('NotEmpty')12. ->addValidator($loginDoesntExist)13. ->addValidator('StringLength', false, 3, 20)14. ->setDescription("Login between 3 and 20 alphanumerics characters.");15. }16.}La création de notre élément HTML passe par l’utilisation de Zend_Form_Element_Text qui prend 2 paramètres :
- Son identifiant
- et des attributs HTML (ici la taille du champ)
- StripTags : Enlève les caractères HTML
- StringTrim : Enlève les espaces dans la chaîne de caractère.
- StringLength : Vérifie la longeur de la chaine de caractère.
- NotEmpty : Vérifie si la chaine existe.
Dans notre cas, nous avons besoin de vérifier l’unicité du login dans la base de donnée, pour cela, le Zend Framework possède un validateur très simple d’utilisation mais très pratique : Zend_Validate_Db_NoRecordExists.
Il prend en paramètres :
- Le nom de la table (ici membres)
- Et le champ à regarder (ici login )
Pratique non?
Passons ensuite à l’adresse email qui ressemble tout particulièrement au login, sauf qu’ici nous validons un email et utilisons le validateur EmailAddress :
01.$emailDoesntExist = new Zend_Validate_Db_NoRecordExists('membres', 'email');02.$email = new Zend_Form_Element_Text("email", array('size' => 25));03.$email ->setLabel('Email address')04. ->addFilter('StripTags')05. ->addFilter('StringTrim')06. ->addValidator('NotEmpty')07. ->addValidator($emailDoesntExist)08. ->addValidator('EmailAddress')09. ->setDescription("Require a valid email address.");Les champs de password sont eux aussi très simple :
01.$password = new Zend_Form_Element_Password("password", array('size' => 25));02.$password ->setLabel('Password')03. ->addFilter('StringTrim')04. ->addValidator('NotEmpty');05.$repassword = new Zend_Form_Element_Password("repassword", array('size' => 25));06.$repassword ->setLabel('Retype password')07. ->addFilter('StringTrim')08. ->addValidator('NotEmpty');09.$repassword->setDescription("Retype the previous password to prevent errors.");Ensuite la liste déroulante des pays.
Comme tout le monde le sait sûrement, quand on développe une application sans framework, il est souvent compliquer d’avoir une liste de pays complète et compatible avec plusieurs langues. Le Zend Framework embarque nativement ce genre de fonctionnalités que nous allons utilisé dans notre formulaire.
1.$pays = new Zend_Form_Element_Select("pays");2.$pays ->setLabel('Country')3. ->addMultiOptions(Zend_Locale::getCountryTranslationList(Zend_Registry::get('Zend_Locale')))4. ->addValidator('NotEmpty');Ce qui va nous donner :
Et enfin, il nous faut le composant Captcha qui est directement intégré dans le Zend Framework. Pour pouvoir utiliser ce composant, il faut un compte sur le site de ReCaptcha.net. Une fois inscrit, vous aurez accès à votre clef publique et à une clef privée :
1.$pubKey = 'clef publique';2.$privKey = 'clef privée';3.$recaptcha = new Zend_Service_ReCaptcha($pubKey, $privKey);4.$adapter = new Zend_Captcha_ReCaptcha();5.$adapter->setService($recaptcha);6.$captcha = new Zend_Form_Element_Captcha('recaptcha', array( 'label' => "Captcha", 'captcha' => $adapter));7.$captcha->removeDecorator('label')->removeDecorator('errors');Maintenant il suffit d’ajouter tout ces composants dans votre formulaire et le tour sera joué !
1.$this->addElements(array($login,$email, $password, $repassword, $pays, $captcha));Pour cela, je vais vous fournir un composant qui va vérifier si les Password correspondent entre eux ( à placer dans le repertoire library/App/Validate de votre application). Vous pouvez le télécharger ici.
Mais cela ne suffira pas, il faut maintenant utiliser ce composant.
Pour cela, nous allons re-écrire la méthode de validation du Zend_Form.
1.public function isValid($data)2.{3. $password = $this->getElement('password');4. $password->addValidator(new App_Validate_PasswordMatch($data['repassword']));5. return parent::isValid($data);6.}Pour afficher le formulaire c’est très simple, rendez vous dans le contrôleur MembreController.php et ajouter cela:
1. 1.class MembreController extends Zend_Controller_Action2.{3. function newAction()4. {5. $this->view->form = $form = new Form_Inscription;6. }7.}1.echo $this->translate('Register to Watch My Desk'); ?>
2.echo $this->form; ?>01.class Form_Inscription extends Zend_Form02.{03. public function __construct($options = null)04. {05. parent::__construct($options);06. $this->setName('inscription');07. $login = new Zend_Form_Element_Text("login", array('size' => 25));08. $loginDoesntExist = new Zend_Validate_Db_NoRecordExists('membres', 'login');09. $login ->setLabel('Login')10. ->setRequired(true)11. ->addFilter('StripTags')12. ->addFilter('StringTrim')13. ->addValidator('NotEmpty')14. ->addValidator($loginDoesntExist)15. ->addValidator('StringLength', false, 3, 20)16. ->setDescription("Login between 3 and 20 alphanumerics characters.");17. $emailDoesntExist = new Zend_Validate_Db_NoRecordExists('membres', 'email');18. $email = new Zend_Form_Element_Text("email", array('size' => 25));19. $email ->setLabel('Email address')20. ->setRequired(true)21. ->addFilter('StripTags')22. ->addFilter('StringTrim')23. ->addValidator('NotEmpty')24. ->addValidator($emailDoesntExist)25. ->addValidator('EmailAddress')26. ->setDescription("Require a valid email address.");27. $password = new Zend_Form_Element_Password("password", array('size' => 25));28. $password ->setLabel('Password')29. ->setRequired(true)30. ->addFilter('StringTrim')31. ->addValidator('NotEmpty');32. $repassword = new Zend_Form_Element_Password("repassword", array('size' => 25));33. $repassword ->setLabel('Retype password')34. ->setRequired(true)35. ->addFilter('StringTrim')36. ->addValidator('NotEmpty');37. $repassword->setDescription("Retype the previous password to prevent errors.");38. $pays = new Zend_Form_Element_Select("pays");39. $pays ->setLabel('Country')40. ->setRequired(true)41. ->addMultiOptions(Zend_Locale::getCountryTranslationList(Zend_Registry::get('Zend_Locale')))42. ->addValidator('NotEmpty');43. $pubKey = '';44. $privKey = '';45. $recaptcha = new Zend_Service_ReCaptcha($pubKey, $privKey);46. $adapter = new Zend_Captcha_ReCaptcha();47. $adapter->setService($recaptcha);48. $captcha = new Zend_Form_Element_Captcha('recaptcha', array( 'label' => "Captcha", 'captcha' => $adapter));49. $captcha->removeDecorator('label')->removeDecorator('errors');50. $this->addElements(array($login,$email, $password, $repassword, $pays, $captcha));51. }52. public function isValid($data)53. {54. $password = $this->getElement('password');55. $password->addValidator(new App_Validate_PasswordMatch($data['repassword']));56. return parent::isValid($data);;57. }58.}Modification de l’apparence du formulaire
Pour le moment notre formulaire est, nous pouvons le dire, sacrement moche ! Néanmoins tout ce dont nous avons besoin est présent !Maintenant on va re-skinner le formulaire car pour le moment il utilise les éléments DD-DT et nous voulons utiliser des Li.
Pour faire cela, nous allons créer une vue dans /application/modules/frontend/views/scripts/membre nommé registerform.phtml. C’est dans cette vue que nous allons définir la manière de rendu de notre formulaire.
Nous allons appeler cette vue dans notre formulaire, avant la fin du constructeur :
1.$this->setDecorators( array( array('ViewScript', array('viewScript' => 'membre/registerform.phtml'))));et ensuite il nous reste à implémenter ce fichier .phtml :
01.02. method="< ?= $this->escape($this->element->getMethod()) ?>" id="myform">03.04. echo $this->translate('Create your account'); ?>05. class="formRegister">06. foreach($this->element as $element): ?>07. 08. 09. echo $this->formLabel($element->getName(),$this->translate($element->getLabel())) ?>10. echo $element->renderDescription() ?>11. 12. if($element->getName() == "recaptcha"): ?>13. echo $element->render();?>14. else:?>15. echo $this->{$element->helper}(16. $element->getName(),17. $element->getValue(),18. $element->getAttribs(),19. (method_exists($element,'getMultiOptions')) ? $element->getMultiOptions() : ''20. ) ?>21. endif;?>22. echo $this->formErrors($element->getMessages()) ?>23. 24. endforeach; ?>25. 26. "submit" id='submit' value="translate('Register'); ?>" />27.28.Excellent non? Bon ok, vous allez surement me dire que c’est toujours aussi moche …
Vous avez raison !
Mais essayer d’ajouter ces lignes de CSS dans le fichier public/css/main.css :
001.#myform {002. font-size: 1em;003. margin: 0 auto;004. width: 560px;005.} 006.#myform fieldset {007. background-color: #F2F9FE;008. border: 1px solid #AEDCF5;009. margin: 10px 0 20px;010. padding: 20px 15px 10px;011. position: relative;012.} 013.#myform fieldset:hover {014. background-color: #FFFCCD;015. border: 1px solid #FFDB60;016.} 017.#myform fieldset:hover input, #myform fieldset:hover textarea {018. background-color: #FFFFFF;019. border: 1px solid #FFDB60;020.} 021.#myform fieldset:hover select {022. background-color: #FFFFFF;023. border: 1px solid #FFDB60;024.}025.#myform legend {026. color: #FF5A00;027. font-family: Georgia, "Times New Roman", Times, serif;028. font-size: 16px;029. font-style: italic;030. left: 10px;031. position: absolute;032. top: -8px;033.} 034.#myform fieldset:hover legend, .designField:hover legend {035. color: #3F87E9;036.} 037.#myform label {038. color: #000000;039. display: block;040. float: left;041. font-weight: bold;042. margin: 0 10px 0px 0;043. padding: 0;044. text-align: right;045. width: 190px;046. font-size: 12px;047.}048.#myform input {049. border: 1px solid #AEDCF5;050. color: #3F87E9;051. font-size: 12px;052. line-height: 24px;053. height: 24px;054. margin: 0 0 13px;055. padding: 7px 3px 3px 3px;056. width: 210px;057.}058.#myform span {059. margin-right: 20px;060. display:block;061. float: left;062. width: 190px;063. text-align: right;064.}065.#myform input:hover {066. border: 1px solid #41A9D8;067.}068.#myform textarea {069. border: 1px solid #AEDCF5;070. color: #3F87E9;071. font-size: 1em;072. width: 215px;073.}074.#myform select {075. border: 1px solid #AEDCF5;076. color: #3F87E9;077. font-size: 12px;078. height: 29px;079. margin: 0 0 13px;080. padding: 4px 3px 2px;081. width: 220px;082.}083.#myform select option {084. padding-left: 10px;085.}086.#myform select:hover {087. border: 1px solid #41A9D8;088.} 089.#myform p {090. text-align: center;091.}092.#myform #submit {093. border: 1px solid #000;094. height: 35px;095. padding: 5px;096. width: 92px;097. font-weight: bold;098. color: #000;099. background: #c0c0c0;100. line-height: 35px;101. font-variant: small-caps;102. margin: 0;103.}104.#myform #submit:hover {105. border: 0 none;106. cursor: pointer;107.}Finitions du formulaire.
Maintenant passons à la traduction du formulaire.Il y a plusieurs choses à voir, par exemple :
- Traduction du Formulaire
- Traduction des messages d’erreurs
- Ajout des messages dans nos fichiers de traductions.
1.Zend_Form::setDefaultTranslator($translate);2.Zend_Validate_Abstract::setDefaultTranslator($translate);01.return array(02.'hello' => 'Bonjour et bienvenue sur notre site',03.'english' => 'Anglais',04.'french' => 'Français',05.'Watch My Desk - Show Off your Geekstation' => 'Watch My Desk - Show Off your Geekstation',06.'Browse' => 'Explorer',07.'Join Now' => "S'inscrire",08.'Login' => 'Identification',09.'Your Desk' => 'Ton Bureau',10.'Show off' => 'Montre',11.'your geekstation.' => 'ton bureau de geek',12.'Watch My Desk is a website where you can share, browse and rate pictures of desks and computers of the world.' => 'Watch my desk est un site où vous pouvez partager, explorer et noter des photos du bureaux et ordinateurs du monde entier',13.'Join the website to share your desk or post comments, just in 2 clics !' => 'Inscrivez vous pour partager vos bureaux, poster des coms... en 2 clics !',14.'Join now and show off your desk with the community !' => 'Inscris-toi maintenant et partage ton bureau de geek avec la communauté !',15.'Login between 3 and 20 alphanumerics characters.' => 'Pseudo compris entre 3 et 20 caractères alphanumériques.',16.'Require a valid email address.' => 'Adresse email valide requise.',17.'Retype the previous password to prevent errors.' => 'Saisissez de nouveau le mot de passe.',18.'Create your account' => 'Créez votre compte',19.'Country' => 'Pays',20.'Retype password' => 'Password (encore)',21.'Register' => 'S\'enregistrer'22.);Valider notre formulaire dans le controller
Rendez-vous dans notre contrôleur MembreController (dans application/modules/frontend/controllers).Il va falloir procéder à la validation de notre formulaire :
01.class MembreController extends Zend_Controller_Action02.{03. function newAction()04. {05. $this->view->form = $form = new Form_Inscription;06. if($post = $this->_request->isPost()){07. $formData = $this->getRequest()->getPost();08. if($form->isValid($formData)){09. // Traitement10. }else{11. $form->populate($formData);12. }13. }14. }15.}Ajout du membre dans la base de donnée
Pour ajouter un membre une fois la validation terminer nous allons utiliser notre modèle Model_DbTable_Membres créé dans les premiers épisodes.Mais avant nous allons ajouter un champs dans la base de donnée. Ce champs sera nommé token, sera un varchar de 32 caractère et servira à l’envoie d’un mail de confirmation à notre utilisateur !
Rendez vous dans le fichier Model_DbTable_Membres pour créer une nouvelle méthode d’ajout de membre.
01.public function addUser($data)02. {03. $otherData = array(04. 'ip_inscription' => $_SERVER['REMOTE_ADDR'],05. 'pass' => md5($data['password']),06. 'date_inscription' => date('Y-m-d H:i:s'),07. 'lvl' => 1,08. 'etat' => 0, // Doit valider son compte09. 'token' => md5($data['email'].$_SERVER['REMOTE_ADDR'].$data['password'])10. );11. unset($data['recaptcha_challenge_field'],12. $data['recaptcha_response_field'],13. $data['repassword'],14. $data['password']);15. $userData = array_merge($data, $otherData);16. $this->insert($userData);17. return $otherData['token'];18. }On voit aussi que le champ token est utiliser ici, c’est un md5 de l’email, de l’ip et du mot de passe de l’utilisateur.
Une fois cela fait, placez-vous dans la partie traitement du code précédent et ajoutez :
01.$db = Zend_Db_Table::getDefaultAdapter();02.$db->beginTransaction();03.try{04. $user = new Model_DbTable_Membres();05. $token = $user->addUser($formData);06. $db->commit();07. Zend_Session::regenerateId();08.}catch (Exception $e)09.{10. $db->rollBack();11. throw $e;12.}13.$this->_redirect('/');Dans le bloc try, on créer un objet Membres, on utilise la méthode addUser écrite précédemment, et on commit. Si une erreur se produit dans ce bloc, on rollback directement.
Je trouve cela très pratique de pouvoir gérer manuellement les transactions SQL personnellement !
Après le commit(), on génère un nouvel identifiant de session, uniquement pour la sécurité.
Email de validation
Et voila ! Nous pouvons nous inscrire sur WatchMyDesk! Mais le compte par défaut n’est pas actif… il va donc falloir envoyer un mail à l’utilisateur pour lui demander la confirmation de son compte.Pour faire cela, rendez vous dans le fichier application/configs/application.ini et ajouter ces lignes de configurations juste avant la ligne [development : production] :
1.[mail]2.mail.from.name = WatchMyDesk Support3.mail.from.address = support@watchmydesk.com4.mail.config.ssl = tls5.mail.config.port = 5876.mail.config.auth = login7.mail.config.username = votre email pour gmail8.mail.config.password = votre mot de passe gmailDirection ensuite le fichier Bootstrap.php pour ajouter une méthode de configuration pour les emails.
1.protected function _initMails()2.{3. $config = new Zend_Config_Ini(APPLICATION_PATH . '/configs/application.ini', 'mail');4. $mailConfig = $config->toArray();5. Zend_Registry::set('Mail_Config', $mailConfig['mail']['config']);6.}Revenons dans la méthode newAction de notre contrôleur membreController pour finir le code d’envois d’email juste après l’ajout d’un utilisateur:
01.$smtpConnection = new Zend_Mail_Transport_Smtp('smtp.gmail.com', Zend_Registry::get('Mail_Config'));02.$mail = new Zend_Mail('utf-8');03.$mail ->addTo($formData['email'])04.->setFrom('support@watchmydesk.com', 'WatchMyDesk Support')05.->setSubject('Bienvenue sur WatchMyDesk')06.->setBodyHtml('07.Dear '.$formData['email'].'08.Welcome to WatchMyDesk !!09.Please visit this url to activate your account:10.'.ROOT_URL.'/membre/activate/id/'.$token.'11.See you there,12.The WatchMyDesk Team');13.$mail->send($smtpConnection);Vous avez du remarquer que nous demandons l’activation du compte par un lien dans l’email. Il va donc falloir créer l’action et la méthode du model Membre pour valider l’utilisateur.
Dans le contrôler membre:
01.public function activateAction()02.{03. $token = $this->getRequest()->getParam('id');04. if($token){05. $user = new Model_DbTable_Membres();06. $user->validateUserByToken($token);07. }08. $this->_redirect('/');09.}Dans le modèle Membres:
1.public function validateUserByToken($token)2.{3. $where = array('token = ?' => (int)$token);4. $this->update(array('etat' => 1), $where);5. return $user;6.}Conclusion
Ok, cet article est long mais il est très complet sur le processus d’inscription d’un utilisateur. Je vous conseille de prendre le temps d’analyser le code créer ici, de tester par vous même !Retrouver la gestion des formulaire pour Symfony sur la FermeDuWeb:
N’hésitez pas à me poser votre question dans les commentaires! et Bonne journée !
