Depuis la version 1.1, Symfony propose un framework de génération de formulaire, respectant le modèle MVC, et bien entendu bati selon un modèle objet robuste.
Pour l’avoir un peu poussé dans ses retranchements, je dois avouer que je suis quelque peu impressionné par la qualité de l’ouvrage. Aujourd’hui, je vous propose un exemple de fonctionalité intéressante : les inclusions de formulaires.
Un formulaire peut en cacher un autre
Pour illustrer mon propos, prenons un modèle simple (dans schema.yml) :
propel:
user:
id:
name: varchar(255)
email: varchar(255)
address_id:
address:
id:
number: integer
street: varchar(255)
town: varchar(60)Un utilisateur a une seule adresse, facile. Pour faire bonne mesure, j’ai quand même partitionné mes tables. Ajoutons quelques données de test dans le répertoire fixtures :
Address:
a1:
number: 1
street: boulevard Belleville
town: Paris
a2:
number: 666
street: cours gambetta
town: Montpellier
User:
robert:
name: Garcin Fony
email: garcin.fony@example.com
address_id: a1Puis, achevons de créer notre environnement de démonstration, en créant le modèle, chargeant les données, et préparant un module :
symfony propel:build-all-load frontend symfony generate:module frontend user
Édition d’un utilisateur
Je veux utiliser la puissance du framework de formulaires pour éditer un utilisateur. Facile, on va d’abord réaliser une action pour prendre en charge la création et la validation du formulaire :
public function executeEdit($request) { $user = UserPeer::retrieveByPk($request->getParameter('id')); $this->forward404Unless($user); $this->userForm = new UserForm($user); if($request->isMethod('post') && $this->userForm->bindAndSave($request->getParameter('user'))) { $this->redirect('@homepage'); } }
Ensuite, dans mon template editSuccess.php, il ne me reste qu’à afficher le formulaire :
<form action="" method="post"> <?php echo $userForm ?> <input type="submit" value="modifier" /> </form>
Le résultat n’est pas trop mal :
Génial ! Symfony détecte automatiquement la clé étrangère, et adapte son formulaire en conséquence en me fournissant une liste déroulante des adresses (Au passage, remarquez que ce phénomène a nécessité l’ajout d’une méthode __toString dans la classe adresse, on n’a rien sans rien).
Bon, c’est bien beau, mais moi, j’espérais plutôt pouvoir éditer l’adresse en question dans le même formulaire. Pas de problèmes, nous allons modifier notre formulaire avec la fonction magique embedForm pour qu’il embarque un autre formulaire de modification de l’adresse.
La fonction embedForm permet, comme son nom l’indique, d’embarquer un formulaire dans un autre. Les validateurs sont également pris en compte. En alternative, selon les cas, on préférera la fonction mergeForm, qui permet de fusionner les formulaires.
Dans lib/form/UserForm.class.php :
class UserForm extends BaseUserForm { public function setup() { parent::setup(); $this->widgetSchema['address_id'] = new sfWidgetFormInputHidden(); $this->embedForm('address', new AddressForm($this->getObject()->getAddress())); } }
Et voilà ! Sans toucher le moins du monde au template, on se retrouve avec le résultat escompté :
Rhââ Lovely ! (comme dirait l’autre). Tout ça en 5 lignes de codes et 4 de templates. Bon, par contre, notre adresse n’est pas mise à jour à la soumission du formulaire. Embêtant… Il va nous falloir surcharger la méthode updateObject pour prendre en compte le formulaire embarqué. Dans la même classe :
public function updateObject() { parent::updateObject(); $address = $this->getObject()->getAddress(); $values = $this->getValues(); $address->fromArray($values['address'], BasePeer::TYPE_FIELDNAME); $address->save(); return $this->object; }
À ce moment, notre adresse sera sauvegardée en même temps que l’utilisateur. Pour la beauté de la démonstration, je n’ai pas rajouté de gestion des exceptions, mais l’idée est là.
Sur ce, je vous laisse vous amuser avec les formulaires. À la prochaine !



13 Commentaires
Sympa ce petit tuto. J’éspère que d’autres suivront du même acabit
A noter que depuis hier soir, le save du form principal est récursif (ce qui était déjà avant le cas avec les form doctrine je crois d’ailleurs) donc plus besoin de surcharger updateObject (a voir comment ça se goupille avec l’adress_id par contre)
ps : une petite coquille sur le label du checkbox de ton formulaire de commentaire ( »un nouveau commetnaire »)
Héhé Geoffrey m’a devancé, je venais faire la même remarque
Ah, ça c’est une amélioration intéressante. Sera-t-elle présente sur la branche 1.1 ?
Hmmm, vraisemblablement pas, pour des raisons de compatibilité ascendante…
ça gère les propel form la 1.1 ?
Geoffrey> Oui
Dommage que ce genre de tutoriel ne soit pas étendu aux problématiques de la CREATION de nouveaux éléments !
Merci d’avoir pris de ton temps pour ces explications en tout cas,
bonne continuation.
Bonjour,
Le tuto est bien, mais comme l’a mentionné Adrien il ne traite pas de la problématique de l’inscription.
Je dispose d’un table user (id, nom, prenom, email, password) et d’une autre user_profil(id, user_id, birthday, ecole, genre, religion…)
Je ne sais pas comment faire pour que lors de l’ajout d’un nouvel utilisateur, il me crée automatiquement une entrée avec l’id user crée dans la table profil.
Un pti conseil à me donner ?
Merci
Cordialement
> Création de nouveaux éléments
Pour les objets du modèle, il suffit de mettre un $this->embedForm(…) ; et Symfony 1.2 s’occupe de tout : sfFormORM disposant de méthodes save/updateEmbeddedForms qui sont appelées automatiquement.
Dans symfony 1.4 j’obtiens :
Unknown record property / related component « adress » on « User »
non c bon.
Je m’étais emmêler les pédales
Pour info :
Une nouveauté de symfony 1.3 est la méthode sfFormDoctrine::embedRelation() qui offre au développeur la possibilité d’imbriquer automatiquement des relations n-à-plusieurs dans un formulaire.
cf :
http://www.symfony-project.org/more-with-symfony/1_4/fr/06-Advanced-Forms#chapter_06_imbriquer_facilement_des_formulaires_doctrine
bonjour, deux remarques
1) il faut declarer
public function updateObject($values = null)
2) Class ‘BasePeer’ not found
pourrais tu expliquer cette derniere ligne ?
merci
One Trackback
[...] Le blog d’un développeur Bonnes pratiques, astuces, culture web (non, pas 2.0), etc. Sauter vers le contenu À proposArchives « Mixons les formulaires avec Symfony [...]