Piste: • responsexul • responsezip • responsexul • controllers • responserss • simple • responserdf • webservices • responsexml • utilisation
Wiki: Index - Derniers changements - Back link
Section : Utiliser un formulaire dans un contrôleur
| « Format des fichiers jForms | ^ jForms : des formulaires automatiques | Affichage d'un formulaire » |
Les données d'un formulaire jforms sont stockées en sessions. On manipule ces données au travers d'un objet formulaire, instance d'une classe héritant de jFormsBase. Cette classe est générée automatiquement à partir du fichier XML que vous fournissez. Comme pour les DAOs, elle est stockée dans un cache évitant de la recréer à chaque utilisation.
Dans les contrôleurs, vous créez, récupérez et détruisez cet objet formulaire via les méthodes statiques de l'objet jForms.
Les actions à mettre en oeuvre ¶
Comme il est déjà expliqué dans le guide sur les formulaires classiques, pour faire une gestion complète de la saisie d'un formulaire, la création des actions suivantes est recommandée (les noms utilisés sont juste à titre d'exemple, vous utilisez les noms que vous voulez bien sûr):
- une action “prepare” qui crée une nouvelle instance d'un objet formulaire avec jforms. S'il faut pré-remplir le formulaire, cette action devra le faire aussi. Redirection vers “show”.
- une action “show” qui récupère l'instance du formulaire, et l'utilise dans un template pour l'afficher avec les éventuelles erreurs de saisie trouvées lors d'une validation précédente. La soumission du formulaire par l'utilisateur dirigera vers l'action “save”.
- une action “save”. l'instance du formulaire est récupérée auprès de jForms, et elle est remplie avec les données reçues du navigateur. Elle pourra ensuite lancer la vérification des données dans le formulaire. Si il y a des erreurs, il y aura une redirection vers “show”. Sinon on pourra traiter les données (sauvegarde en base de donnée par exemple) et ensuite rediriger vers “end”
- une action “end”, qui détruira l'instance du formulaire jforms (ce qui effacera les données correspondantes en session), et affichera éventuellement une page de confirmation, ou alors redirigera vers une autre action quelconque…
Créer une instance d'un formulaire ¶
Avant de pouvoir utiliser jForms, il faut bien sûr créer un fichier xml décrivant le formulaire, et il faut ensuite avant toute utilisation, qu'une de vos actions crée une instance de votre formulaire. Cela se fait au moyen de la méthode statique create de la classe jForms. Comme toutes les autres méthodes statiques de la class jForms, elle prend en premier argument le sélecteur du fichier xml, et un deuxième argument facultatif qui est un identifiant de l'instance à créer.
En admettant que votre fichier xml soit “contact.form.xml” dans le module “main” :
$form = jForms::create("main~contact");
La variable $form contiendra un objet qui aura pour classe, celle créée lors de la lecture du fichier XML, et qui hérite de jFormsBase. Vous utiliserez ensuite cette variable $form pour manipuler les données du formulaire.
Dans cette exemple, nous n'indiquons pas le deuxième paramètre. En effet celui-ci ne sert que lorsque l'on veut éditer des informations qui existent déjà. Par exemple, pour un formulaire pour éditer un produit qui est en base de donnée, on indiquera l'identifiant de ce produit.
Pourquoi ? Avec un navigateur web, l'utilisateur a la possibilité d'ouvrir plusieurs pages à la fois. Il a donc la possibilité d'afficher plusieurs fois la même page qui afficherait par exemple ce formulaire d'édition de produit, mais avec à chaque fois un produit différent. Pour éviter qu'à chaque fois que l'on ouvre cette page, donc qu'à chaque fois que l'on créé une instance du formulaire jForms, on aille écraser les données en sessions du même formulaire d'un autre produit ouvert en même temps, on donne un identifiant de formulaire. Ainsi il n'y a pas de collision des données de chaque instance de formulaire. On peut donner ce que l'on veut comme identifiant (une chaine, un nombre), et en général on donne l'identifiant de l'enregistrement SQL quand il s'agit de l'édition de ce genre d'information.
En admettant que votre fichier xml soit product.form.php dans le module shop, voici un exemple de création d'un formulaire pour éditer un produit existant.
$form = jForms::create("shop~product", $product_id);
Bien sûr, quand il s'agit d'afficher un formulaire vierge pour éditer un nouveau produit, il n'y a pas d'identifiant, et vous n'êtes pas obligé d'en donner un.
$form = jForms::create("shop~product"); // édition d'un nouveau produit
Pour l'exemple précédent avec le formulaire de contact, nous n'indiquons pas d'identifiant, car on émet l'hypothèse ici qu'il s'agit d'un formulaire pour que l'utilisateur envoi une demande de contact : ce sera donc toujours un formulaire vierge.
Initialisation d'un formulaire ¶
Après la création d'un formulaire, il est peut être nécessaire de le pré-remplir.
Initialisation simple ¶
Pour cela, vous utiliserez la méthode setData sur l'objet formulaire, qui accepte en argument, le nom du champ à préremplir, et la valeur à lui donner :
$form->setData("prenom","Laurent");
Les valeurs peuvent être récupérées d'ailleurs, comme bon vous semble.
Initialisation avec un dao ¶
Cependant, si vous voulez utiliser un dao, il existe un moyen rapide pour remplir un formulaire. La méthode initFromDao() permet d'utiliser un DAO pour remplir plusieurs champs du formulaire. Il suffit d'indiquer à cette méthode le selecteur du dao à utiliser. Par défaut il prendra la valeur de l'identifiant du formulaire comme identifiant de l'enregistrement à récupérer. Mais vous pouvez indiquer un autre identifiant dans le deuxième argument.
$form = jForms::create("shop~product", $product_id); $form->initFromDao("shop~products");
Ici le formulaire sera prérempli avec les valeurs de l'enregistrement dont la clé est $product_id, et le dao “shop~products” sera utilisé pour cette lecture.
Cependant, seuls les champs de saisie qui ont le même nom que des propriétés du dao indiqué seront pré-rempli. Les autres resteront vides.
Notez que vous pouvez utiliser plusieurs daos pour pré-remplir les champs. En effet on peut avoir besoin d'un formulaire qui contient des champs de saisie qui seront stockés dans plusieurs tables.
Initialisation d'un champs à choix multiple ¶
Pour les champs <checkboxes> et <listbox multiple=“true”>, la valeur à initialiser n'est pas forcément une simple valeur, mais une liste de valeurs qui correspondent à tous les choix qu'il faut pré-sélectionner. (Attention, on parle bien ici des valeurs présélectionnées, pas de la liste des choix).
On peut donc les initialiser avec setData, en leur passant un tableau contenant les valeurs des choix à présélectionner :
$form->setData('categories', array(5, 8, 10));
En général cependant, ces listes de valeurs sont stockées dans une base de données, dans ce qu'on appelle une table de jointure. C'est à dire une table qui fait la jointure entre deux tables, et dont la clé primaire est constituée de deux clés étrangères, l'une et l'autre appartenant à une autre table. Par exemple, on a une table pour les produits ('products'), une table pour les catégories de produits ('categories'), et si un produit peut appartenir à plusieurs catégories, il faut une table de jointure ('products_categories'), contenant les clés des produits et les clés des catégories qui sont en relation (product_id et category_id).
Pour initialiser la listbox ou les cases à cocher, il va donc aller lire dans cette table 'products_categories' les relations. Il existe pour cela une méthode, initControlFromDao() :
$form->initControlFromDao("categories", "shop~products_categories");
Le dao “shop~products_categories” sera utilisé pour lire les valeurs sélectionnées pour le champs catégories. jForms s'attend ici à ce que la première clé déclarée dans le dao corresponde à l'identifiant du produit, et la deuxième clé à l'identifiant des catégories. Si ce n'est pas le cas, il faut alors indiquer les noms de ces clés dans le dao, dans un array à passer en troisième paramètre :
$form->initControlFromDao("categories", "shop~products_categories", array('product_id','category_id'));
Vu qu'il s'agit dans cet exemple de la saisie d'un enregistrement product, et que l'identifiant du formulaire correspond à l'identifiant du produit, la valeur de cet identifiant sera utilisée comme critère de recherche dans la table, pour récupérer les id de catégories correspondantes.
Définir les choix d'un champs à multiple choix ¶
Dans le fichier xml jforms, vous avez vu que pour indiquer la liste des choix possibles dans un <menulist>, une <listbox>, un <radiobuttons> ou un <checkboxes>, vous pouviez indiquer une liste de valeurs statiques, ou un dao qui servira à récupérer les choix.
Il peut cependant arriver que cela soit insuffisant, et que le remplissage dépende de critères ou autre. Dans ce cas, vous n'indiquerez pas de balise <item> ni d'attribut dao* dans le fichier xml. Et vous indiquerez la liste des choix dans votre contrôleur, des manières suivantes.
// récupérez vos données dans un tableau associatif, $datas = array(...); // on récupère le contrôle et on lui indique les données $form->getControl('nom_du_control')->datasource->datas = $datas;;
$datas est un tableau dont les clés sont les valeurs des choix, et les valeurs sont les libellés des choix.
Note : ce remplissage doit se faire dans la même action que celle qui affiche le formulaire. Ces données sont perdues à la fin de l'action.
Récupérer une instance d'un formulaire ¶
Dans une action spécifique, vous allez créer un formulaire avec jForms::create(), mais dans d'autres actions, vous aurez besoin de récupérer le formulaire créé, pour en manipuler ses données. Pour cela il y a deux méthodes statiques de jForms : get() et fill().
La méthode get() permet de récupérer simplement l'objet formulaire. Comme pour create(), vous indiquez un sélecteur :
$form = jForms::get("shop~product");
Si vous aviez donné un identifiant à la création, il faudra le donner aussi ici (récupéré ici à partir des paramètres de la requête http) :
$product_id = $this->param('id'); $form = jForms::get("shop~product", $product_id);
Note : la méthode get renvoie null si le formulaire n'existe pas. Cela veut probablement dire que l'utilisateur a été à l'url de l'action courante sans passer par les urls de l'action qui a créé le formulaire. Il faudrait alors rediriger vers ces actions si $form est null. Ou alors créer directement le formulaire, ce qui peut être suffisant pour de simples formulaires.
$form = jForms::get("main~contact"); if ($form === null) { $form = jForms::create("main~contact"); }
La méthode fill() récupère aussi le formulaire (c'est à dire appel jForms::get(), mais exécute aussi une opération supplémentaire : elle remplie le contenu du formulaire avec les données trouvées en paramètres de la requête HTTP. En clair, elle est à utiliser lors de la réception du formulaire rempli par l'utilisateur (voir la section plus loin sur l'utilisation d'un formulaire après submit).
$product_id = $this->param('id'); $form = jForms::fill("shop~product", $product_id);
Note: l'identifiant (ici id) doit être actuellement récupéré manuellement avant de récupérer le formulaire, mais il est prévu dans les versions ultérieures que cela puisse se faire automatiquement.
Gérer un formulaire après submit ¶
Une fois un formulaire créé, il faut, dans une action l'afficher, ce qui est expliqué dans un chapitre à part. Et dans une autre action, qui sera appelée quand l'utilisateur validera le formulaire, il faudra gérer les données saisies : récupération des données, vérification de leur contenu et enfin traitement (stockage par exemple).
Remplissage à partir des données saisies ¶
Vous l'avez déjà vu un peu plus haut, pour récupérer l'objet formulaire tout en le remplissant à partir des données reçues du navigateur, il suffit d'appeler jForms::fill():
$form = jForms::fill("main~contact");
Cela est en fait équivalent à
$form = jForms::get("main~contact"); $form->initFromRequest();
Vous pouvez aussi utiliser la méthode setData sur le formulaire pour remplir vous même le contenu du formulaire :
$form = jForms::get("main~contact"); $form->setData('nom', $this->param('nom'));
Vérification des données ¶
Une fois le formulaire récupéré avec les bonnes données, il est souvent préférable d'en vérifier exactement le contenu avant de traiter les données. Vous avez à votre disposition la méthode check() qui vérifie les données en fonction de ce que vous avez indiqué dans le fichier xml (l'aspect obligatoire de la saisie, le type de donnée pour les inputs etc…). La méthode check() renvoi true si la vérification est bonne, ou false si il y a des erreurs dans le formulaire.
En général, si la validation échoue, vous avez simplement à réafficher le formulaire : les erreurs s'afficheront automatiquement et l'utilisateur devra corriger.
$form = jForms::fill("main~contact"); if (!$form->check()) { // invalide : on redirige vers l'action d'affichage $rep = $this->getResponse('redirect'); $rep->action='module~default:show'; return $rep; }
Vous pouvez, bien sûr, faire des vérifications approfondies. Vous pouvez alors utiliser la méthode getData pour récupérer la valeur d'un champ de saisie, et setErrorOn pour indiquer une erreur sur un champ.
$form = jForms::fill("main~contact"); if (!$form->check()) { // invalide : on redirige vers l'action d'affichage $rep = $this->getResponse('redirect'); $rep->action='module~default:show'; return $rep; } $ok = true; $valeur = $form->getData('nom'); if( strpos($valeur, 'azerty') !== null) { $ok = false; $form->setErrorOn('nom', 'tu as un nom bizarre toi !'); } // autres vérifications //.... if (!$ok) { // invalide : on redirige vers l'action d'affichage $rep = $this->getResponse('redirect'); $rep->action='module~default:show'; return $rep; }
Stockage des données ¶
Une fois la vérification faite, vous pouvez extraire les données du formulaire avec la méthode getData() ou getDatas() (avec un s) qui renvoie toutes les données sous forme de tableau. Ensuite libre à vous d'en faire ce que vous voulez : les stocker avec jDb ou jDao, les envoyer par mail etc…
Stockage via un dao ¶
Tout comme il y a initFromDao pour initialiser le formulaire, il y a l'opération inverse saveToDao. Cette méthode permet donc d'enregistrer plusieurs champs via un dao. Les valeurs des champs dont les noms correspondent à des propriétés du dao indiqué seront utilisées pour renseigner les propriétés du dao correspondantes, et le tout sera enregistré dans l'enregistrement dont la clé est indiqué dans l'id du formulaire. Si l'id du formulaire est inexistant, un nouvel enregistrement sera créé, plutôt qu'une mise à jour d'un enregistrement existant.
$form->saveToDao('shop~products');
Dans certains cas il peut être utile de récupérer la clé primaire d'un enregistrement créé à l'aide de la méthode saveToDao.
$primaryKey = $form->saveToDao('shop~products');
Stockage des valeurs d'un champ à choix multiples ¶
Il y a la méthode saveControlToDao, qui est l'opération inverse de initControlFromDao. Elle permet donc de sauvegarder les valeurs sélectionnées d'un ensemble de cases à cocher ou d'une liste à choix multiples, dans une table de jointure.
$form->saveControlToDao('categories', 'shop~products_categories');
Le premier paramètre est le nom du champ concerné, et le deuxième le dao utilisé pour le stockage.
Stockage des fichiers ¶
Si le formulaire contient des champs de téléchargement de fichiers, il vous faut sauver les fichiers quelque part. Vous avez pour cela deux méthodes, saveFile() et saveAllFiles. La première pour sauvegarder un fichier précis, et l'autre pour copier tous les fichiers reçus dans un répertoire. Sachez que dans les données du formulaire, la valeur du champ (que l'on récupère via getData) contient le nom du fichier original. Si vous avez besoin de stocker un autre nom, faites un setData.
saveFile() prend en argument le nom du champ contenant le fichier. Par défaut, le fichier est alors stocké dans le répertoire var/uploads/nommodule~nomform/. Vous pouvez indiquer un autre répertoire en donnant son chemin en deuxième paramètre de saveFile(). Et si vous voulez stocker le fichier sous un nom différent, indiquez le en troisième paramètre.
Exemple :
$form->saveFile('photo'); $form->saveFile('photo', JELIX_APP_WWW_PATH.'images/photos/'); $form->saveFile('photo', JELIX_APP_WWW_PATH.'images/photos/', $id.'.png'); $form->saveFile('photo', '', $id.'.png');
saveAllFiles sauve tout les fichiers, sans distinction, dans un même répertoire. Le répertoire par défaut est var/uploads/nommodule~nomform/, mais vous pouvez le changer en l'indiquant en paramètre.
$form->saveAllFiles(); $form->saveAllFiles(JELIX_APP_WWW_PATH.'images/photos/');
Détruire une instance d'un formulaire ¶
Quand un formulaire n'est plus utilisé (la saisie est finie, les données sauvegardées), il est préférable de faire le ménage pour ne pas encombrer la session de données inutiles. Il faut donc détruire le formulaire. Pour cela on utilise jForms::destroy, à laquelle on indique le sélecteur du formulaire, et éventuellement l'identifiant du formulaire concerné.
jForms::destroy("main~contact"); jForms::destroy('shop~products'); jForms::destroy('shop~products', $product_id);

