440 likes | 738 Views
symfony. Formulaires. Helper formulaire. Éviter les <?php echo dans les balises input, etc … <?php echo form_tag('test/save') ?> <form method="post" action="/path/to/save"> <?php echo form_tag('test/save', array( 'method’ => ‘get’, ‘multipart’ => ‘true’,
E N D
symfony Formulaires
Helper formulaire • Éviter les <?php echo dans les balises input, etc … <?php echo form_tag('test/save') ?> <form method="post" action="/path/to/save"> <?php echo form_tag('test/save', array( 'method’ => ‘get’, ‘multipart’ => ‘true’, ‘class’ => ‘simpleForm‘ ) ?> <form method="get" enctype="multipart/form-data" class="simpleForm"action="/path/to/save"> • Fermé par </form>
Helper champs de formulairetexte • tout les champs et contrôles ont un attribut id déduit de l'attribut name <?php echo input_tag('nom', default') ?> <input type="text" name="nom" id="nom" value="default" /> <?php echo textarea_tag('nom', 'default', array( 'size’ => ’10x20‘ ) ) ?> <textarea name="nom" id="nom" cols="10" rows="20"> default </textarea>
Helper champs de formulairechoix <?php echo checkbox_tag('celibataire', 1, true) ?> <?php echo checkbox_tag('permisdeconduire', 'B', false) ?> • <input type="checkbox" name="celibataire" id="celibataire" value="1"checked="checked" /><input type="checkbox" name="permisdeconduire" id="permisdeconduire"value="B" /> <?php echo radiobutton_tag('status[]', 'value1', true) ?> <?php echo radiobutton_tag('status[]', 'value2', false) ?> • <input type="radio" name="status[]" id="status_value1" value="value1"checked="checked" /><input type="radio" name="status[]" id="status_value2" value="value2" />
Helper champs de formulairesélection – syntaxe la plus élégante <?php echo select_tag('payment', options_for_select( array( 'Visa' => 'Visa', 'Eurocard' => 'Eurocard', 'Mastercard' => 'Mastercard‘ ), array('Visa', 'Mastercard') ), array('multiple' => true) ) ?> <select name="payment" id="payment" multiple="multiple"> <option value="Visa" selected="selected">Visa</option> <option value="Eurocard">Eurocard</option> <option value="Mastercard">Mastercard</option></select>
Helper champs de formulaireautres <?php echo input_file_tag('nom') ?> <input type="file" name="nom" id="nom" value="" /> <?php echo input_password_tag('nom', 'valeur') ?> <input type="password" name="nom" id="nom" value="valeur" /> <?php echo input_hidden_tag('nom', 'valeur') ?> <input type="hidden" name="nom" id="nom" value="valeur" />
Helper champs de formulairesoumission <?php echo submit_tag('Sauvegarder') ?> <input type="submit" name="submit" value="Sauvegarder" /> <?php echo submit_image_tag('submit_img') ?> <input type="image" name="submit" src="/images/submit_img.png" /> • helper submit_image_tag() même syntaxe helper image_tag().
Gestion de la soumission mymodule/templates/editAuthorSuccess.php Bonne pratique : utiliser la même action pour afficher et gérer le formulaire. <?php echo form_tag('mymodule/editAuthor') ?> </form> mymodule/actions/actions.class.php public function executeEditAuthor() { if ($this->getRequest()->getMethod() != sfRequest::POST) { // Affichage du Formulaire return sfView::SUCCESS; } else { // Management de la soumission du formulaire $name = $this->getRequestParameter('name'); ... $this->redirect('mymodule/anotheraction'); } }
Gadget date poor <?php echo input_date_tag('datedenaissance', '2005-05-01‘)?> <?php echo select_day_tag('day', 1, array('include_custom’ => ‘Choose a day‘)) ?> • <select name="day" id="day"> <option value="">Choose a day</option> <option value="1" selected="selected">01</option> <option value="2">02</option> ... <option value="31">31</option> </select> <?php echo select_month_tag('month', 1, 'include_custom=Choose a month use_short_month=true') ?> <?php echo select_year_tag('year', 2007, 'include_custom=Choose a year year_end=2010') ?>
Gadget date rich <?php echo input_date_tag('datedenaissance', '2005-05-03', array('rich’ => ’true') ?>
Gadget date valeur par défaut • dates reconnues par la fonction PHP strtotime() <?php echo input_date_tag('test', '2006-04-01', 'rich=true') ?> <?php echo input_date_tag('test', 1143884373, 'rich=true') ?> <?php echo input_date_tag('test', 'now', 'rich=true') ?> <?php echo input_date_tag('test', '23 October 2005', 'rich=true') ?> <?php echo input_date_tag('test', 'next tuesday', 'rich=true') ?> <?php echo input_date_tag('test', '1 week 2 days 4 hours 2 seconds', 'rich=true') ?> • Aucune valeur par défaut <?php echo input_date_tag('test', ‘ ', 'rich=true') ?> • Les Formats de date autre qu’anglais ne fonctionnent pas (14/12/2008)
Rich text TinyMce • http://tinymce.moxiecode.com/ • tinymce/jscripts/tiny_mce/ => web/js/ • settings.yml all: .settings: rich_text_js_dir: js/tiny_mce • <?php echo textarea_tag('name', 'default content', Array( 'rich’ => true, ‘size’ => ‘10x20’, ‘tinymce_options’ => ‘language:"fr",theme_advanced_buttons2:"separator"‘ ) ) ?>
Rich text Fck • http://fckeditor.com/ • fkceditor/ => web/js/ • Myproject/apps/myapp/config/settings.yml all: .settings: rich_text_fck_js_dir: js/fckeditor • <?php echo textarea_tag('name', 'default content', Array( 'rich’ => ‘fck, ‘size’ => ‘10x20’, ) ) ?>
Sélecteur de Pays et de Langage <?php echo select_country_tag('pays', 'AL') ?> <select name="pays" id="pays"> <option value="AF">Afghanistan</option> <option value="AL" selected="selected">Albania</option> <option value="DZ">Algeria</option> <option value="AS">American Samoa</option> … <?php echo select_language_tag('langue', 'en') ?> <select name="langue" id="langue"> <option value="elx">Elamite</option> <option value="en" selected="selected">English</option> <option value="enm">English, Middle (1100-1500)</option> <option value="ang">English, Old (ca.450-1100)</option> <option value="myv">Erzya</option> <option value="eo">Esperanto</option> …
Helper formulaire pour objet <?php echo input_tag('telephone', $customer->getTelephone()) ?> <?php echo object_input_tag($client, 'getTelephone') ?> <input type="text" name="telephone" id="telephone" value="0123456789" />
Helper formulaire pour objet • object_input_tag($object, $method, $options) • object_input_date_tag($object, $method, $options) • object_input_hidden_tag($object, $method, $options) • object_textarea_tag($object, $method, $options) • object_checkbox_tag($object, $method, $options) • object_select_tag($object, $method, $options) • object_select_country_tag($object, $method, $options) • object_select_language_tag($object, $method, $options) • object_password_tag() n’existe pas car ce n’est pas une bonne idée d’initialiser un mot de passe avec quelque chose de saisi par l’utilisateur
Peupler une liste déroulante avec des objets <?php echo options_for_select(array( '1' => 'Steve', '2' => 'Bob', '3' => 'Albert', '4' => 'Ian', '5' => 'Buck' ), 4) ?> <option value="1">Steve</option> <option value="2">Bob</option> <option value="3">Albert</option> <option value="4" selected="selected">Ian</option> <option value="5">Buck</option>
Code contrôleur typique • Dans l’action $options = array(); foreach ($authors as $author) { $options[$author->getId()] = $author->getName(); } $this->options = $options; • Dans le template <?php echo options_for_select($options, 4) ?> • MIEUX! <?php echo objects_for_select($authors, 'getId', 'getName', 4) ?>
Peupler une liste déroulante à base d’une clé étrangère <?php echo select_tag('author_id', objects_for_select( AuthorPeer::doSelect(new Criteria()), 'getId', '__toString', $article->getAuthorId() )) ?> • MIEUX! <?php echo object_select_tag($article, 'getAuthorId') ?> • Le helper devine à partir de la méthode passée en paramètre • le nom de la classe peer associée AuthorPeer • le nom de la méthode peer à utiliser doSelect(new Criteria) • La méthode à utiliser sur chaque objet de la liste __toString() si elle existe ou la clé primaire sinon
Peupler une liste déroulante à base d’une clé étrangère – version explicite • Spécifier la classe peer utilisée pour retrouver les valeurs <?php echo object_select_tag($article, 'getAuthorId', 'related_class=Foobar')?> • Spécifier la méthode peer utilisée pour retrouver les valeurs <?php echo object_select_tag($article, 'getAuthorId','peer_method=getMostFamousAuthors') ?> • Ajouter un item blanc en début de liste <?php echo object_select_tag($article, 'getAuthorId', 'include_blank=true') ?> • Ajouter un item personnalisé en début de liste <?php echo object_select_tag($article, 'getAuthorId', 'include_custom=Choose an author') ?> • Les options de ce helper sont combinables en utilisant un tableau d’options
Validation de formulaire • Formulaire typique <?php echo form_tag('contact/send') ?> Name: <?php echo input_tag('name') ?><br /> Email: <?php echo input_tag('email') ?><br /> Age: <?php echo input_tag('age') ?><br /> Message: <?php echo textarea_tag('message') ?><br /> <?php echo submit_tag() ?> </form> • name est obligatoire et est un texte entre 2 et 100 caractères. • email est obligatoire et est un texte entre 2 et 100 caractères, et doit être valide • age est obligatoire et doit être un entier entre 0 et 120 • message est obligatoire
Les validateurs • Symfony met à disposition des validateurs usuels • Un validateur possède une méthode execute() • Prend une valeur de champ en paramètre • Retourne vrai si la valeur est valide, false sinon • Emploi de sfStringValidator pour les deux premiers champs • Il vérifie que la taille d’un string est compris dans l’intervalle défini lors de l’appel de la méthode initialize()
modules/contact/action/actions.class.php public function validateSend() { $name = $this->getRequestParameter('name'); if (!$name) { $this->getRequest()->setError('name', 'The name field cannot be left blank'); return false; } characters $myValidator = new sfStringValidator(); $myValidator->initialize($this->getContext(), array( 'min' => 2, 'min_error' => 'This name is too short (2 characters minimum)', 'max' => 100, 'max_error' => 'This name is too long. (100 characters maximum)', )); if (!$myValidator->execute($name, $error)) { return false; } return true; }
Processus de validation • Si l’utilisateur rentre une valeur incorrecte • la méthode execute de sfStringValidator retournera false • L’action validateSend échouera • La méthode handleErrorSend sera appelée au lieu de la méthode executeSend() • La classe sfRequest met à disposition une méthode setError(), et une méthode hasError() pour afficher des messages d’erreurs précis • C’est le rôle que jouent les paramètres • min_error • max_error
Fichier de validation • modules/contact/validate/send.yml fields name: required: msg: The name field cannot be left blank sfStringValidator: min: 2 min_error: This name is too short (2 characters minimum) max: 100 max_error: This name is too long. (100 characters maximum) • Toutes les validations sont effectuées • Tous les messages d’erreur seront affichés • La validation globale échoue si au moins une validation de champs échoue • La méthode validateXXX() sera ensuite exécutée si elle existe • Les fichiers de validations sont stockés dans le répertoire validate/ du module et sont nommés nomAction.yml
Réafficher le formulaire • En cas déchec • handleErrorSend() est exécutée si elle existe • Sinon le template sendError.php est affiché • Habituellement si la validation echoue on souhaite réafficher le formulaire • Redéfinir handleErrorSend() en la redirigeant vers l’affichage du formulaire
modules/contact/actions/actions.class.php class ContactActions extends sfActions { public function handleErrorSend() { $this->forward('contact', ‘displayForm'); } public function executeSend() { // traitement du formulaire } } • Si c’est la même action qui affiche le formulaire et qui le traite handleErrorSend() n’a qu’à renvoyer sfView::SUCCESS pour réafficher sendSuccess.php
Code typique de gestion d’un formulaire avec symfony class ContactActions extends sfActions { public function executeSend() { if ($this->getRequest()->getMethod() != sfRequest::POST) { // Prepare data for the template, should be shared return sfView::SUCCESS; } else { // traite le formulaire $this->redirect('mymodule/anotheraction'); } } public function handleErrorSend() { // Prepare data for the template, should be shared return sfView::SUCCESS; } }
Afficher les message d’erreurs dans les formulaires <?php if ($sf_request->hasErrors()): ?> <p>valeurs incorrectes:</p> <ul> <?php foreach($sf_request->getErrors() as $name => $error): ?> <li><?php echo $name ?>: <?php echo $error ?></li> <?php endforeach; ?> </ul> <?php endif; ?>
Afficher les message d’erreurs au niveau des champs <?php echo form_tag('contact/send') ?> <?php if ($sf_request->hasError('name')): ?> <?php echo $sf_request->getError('name') ?> <br /> <?php endif; ?> Name: <?php echo input_tag('name') ?><br /> <?php echo submit_tag() ?> </form> Ou via les helpers Validation <?php use_helper('Validation') ?> <?php echo form_tag('contact/send') ?> <?php echo form_error('name') ?><br /> Name: <?php echo input_tag('name') ?><br /> <?php echo submit_tag() ?> </form>
Repeupler le formulaire • Peut se faire via $sf_params • Simple forward donc la requête est toujours accessible <?php echo input_tag('name', $sf_params->get('name')) ?> • Sinon laisser faire symfony • validate/send.yml fillin: enabled: true param: name: test # nom du forumlaire s’il y en a plusieurs skip_fields: [email] # champs exclus exclude_types: [hidden, password] # types de champs exclus check_types: [text, checkbox, radio, select, hidden] # champs à repeupler content_type: html # html, xml ou xhtml
Transformation des données repeuplées • Pour transformer les données réaffichées • Entities, escaping etc … • validate/send.yml fillin: enabled: true param: name: test converters: # Converters to apply htmlentities: [first_name, comments] htmlspecialchars: [comments]
Les validateurs symfony • sfStringValidator applique des contraintes sur les chaînes de carctères sfStringValidator: values: [foo, bar] values_error: The only accepted values are foo and bar insensitive: false # If true, comparison with values is case insensitive min: 2 min_error: Please enter at least 2 characters max: 100 max_error: Please enter less than 100 characters • sfEmailValidator vérifie la validité d’un adresse email sfEmailValidator: strict: true # name@domaine.ext est valide, sinon RFC822 email_error: This email address is invalid
Les validateurs symfony II • sfNumberValidator vérifie qu’une entrée est bien un nombre et lui applique des contraintes de taille sfNumberValidator: nan_error: Please enter an integer min: 0 min_error: The value must be at least zero max: 100 max_error: The value must be less than or equal to 100 • sfUrlValidator vérifie la validité d’une url sfUrlValidator: url_error: This URL is invalid
Les validateurs symfony III • sfRegexValidator vérifie qu’une entrée est conforme ou non à un masque d’expression régulière compatible perl sfRegexValidator: match: No # spécifie que l’entrée doit vérifier le masque (ne doit pas sinon) match_error: Posts containing more than one URL are considered as spam pattern: /http.*http/si • sfCompareValidator vérifie que deux entrées sont égales fields: password1: required: msg: Please enter a password password2: required: msg: Please retype the password sfCompareValidator: check: password1 compare_error: The two passwords do not match
Les validateurs symfony IV • sfPropelUniqueValidator vérifie qu’une entrée n’existe pas déjà en bas de données (pratique pour le identifiant unique) fields: nickname: sfPropelUniqueValidator: class: User column: login unique_error: This login already exists. Please choose another one. • sfCallbackValidator vérifie que deux entrées sont égales fields: account_number: sfCallbackValidator: callback: is_numeric invalid_error: Please enter a number. credit_card_number: sfCallbackValidator: callback: [myTools, validateCreditCard] # doit renvoyer true ou false invalid_error: Please enter a valid credit card number.
Les validateurs symfony V • sfFileValidator vérifie qu’un fichier uploadé a le bon type mime et la bonne taille fields: image: file: True required: msg: Please upload an image file sfFileValidator: mime_types: - 'image/jpeg' - 'image/png' - 'image/x-png' - 'image/pjpeg' mime_types_error: Only PNG and JPEG images are allowed max_size: 512000 max_size_error: Max size is 512Kb .
DRY – les validateurs nommés validators: myStringValidator: class: sfStringValidator param: min: 2 min_error: This field is too short (2 characters minimum) max: 100 max_error: This field is too long (100 characters maximum) fields: name: required: msg: The name field cannot be left blank myStringValidator: email: required: msg: The email field cannot be left blank myStringValidator: sfEmailValidator: email_error: This email address is invalid
Restriction de validation à la méthode POST ou GET • La validation est appelé par défaut pour la méthode POST • redéfinissable globalement ou champs par champs methods: [post] fields: email: methods: [post, get] # redéfinit la conf globale required: msg: The email field cannot be left blank sfEmailValidator: email_error: This email address is invalid
Validateur personnalisé • Tout validateur hérite de sfValidator • Stocké dans un des répertoires lib/ • La méthode execute() prend la valeur à valider et le message d’erreur en paramètre • La méthode initalize() recoit le singletion context, et les paramètres du fichier YAML en paramètre • Elle doit commencer par appeler la méthode initalize de la classe dont elle dérive (sfValidator) • Elle définit les paramètres si le ichier YAML n’existe pas • Tout validateur peut accéder aux paramètres via $this->getParameterHolder()
Validateur personnalisécode class sfSpamValidator extends sfValidator { public function execute (&$value, &$error) { $re = '/'.implode('.*', array_fill(0, $this->getParameter('max_url') + 1, 'http')).'/is'; if (preg_match($re, $value)) { $error = $this->getParameter('spam_error'); return false; } return true; } public function initialize ($context, $parameters = null) { parent::initialize($context); $this->setParameter('max_url', 2); $this->setParameter('spam_error', 'This is spam'); $this->getParameterHolder()->add($parameters); return true; } }
Validateur personnaliséutilisation • validate/send.yml message: required: msg: The message field cannot be left blank sfSpamValidator: max_url: 3 spam_error: Leave this site immediately, you filthy spammer!
Utilisation de la syntaxe tableau dans les formulaires • PHP permet d’utiliser la syntaxe tableau dans les formulaires <label for="story_title">Title:</label> <input type="text" name="story[title]" id="story_title" value="default" /> • Incidence sur le fichier de validation fields: story{title}: required: Yes
Exécution d’un validateur sur un champs vide • Exemple du changement de mot de passe fields: password1: password2: sfCompareValidator: check: password1 compare_error: passwords mismatch Valide un mot de passe blanc!! fields: password1: group: group_password password2: group: group_password sfCompareValidator: check: password1 compare_error: passwords mismatch Les tests agissant sur un groupe ne s’applique que si un des champs membre n’est pas vide