symfony Formulaires
Helper formulaire Fermé par </form> É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 formulaire texte 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 formulaire choix <?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 formulaire sé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 formulaire autres <?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 formulaire soumission <?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 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()
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: 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: 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 email: msg: The email field cannot be left blank 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); }
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: 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