Depuis la 1.1, les formulaires imbriqués sont gérés grace à la méthode embedForm de la classe sfForm Un exemple avec le module sfDoctrineGuard que l’on veut éttendre avec un profil. La classe du formulaire principal :
class sfGuardUserForm extends PluginsfGuardUserForm { public function configure() { unset( $this['is_active'], ... $this['permissions_list'] ); $profile = new ProfileForm(); unset( $profile['sf_guard_user_id'] ); $this->embedForm('Profile', $profile); } }
L’action :
public function executeIndex(sfWebRequest $request) { $this->form = new sfGuardUserForm(); if( $request->isMethod('post') && $this->form->bindAndSave() ) { $this->getUser()->setFlash('notice', 'Utilisateur enregistré.'); $this->redirect('utilisateur/index'); } }
Le problème c’est que le de bindAndSave() sur le formulaire principal provoque 2 save sur le formulaire embarqué. Du coup si il y a des champs unique dans le formulaire embarqué et surtout un notnull sur la clé de jointure, ca plante. La méthode alternative pour arriver au même résultat : Pas la peine de redéfinir la classe formulaire. Tout se passe dans la classe action ou on va définir les 2 formulaires à utiliser dans la vue et le traitement associé.
public function executeInscription(sfWebRequest $request) { $this->formUser = new sfGuardUserFormInscription(); $this->formProfile = new UtilisateurFormInscription(); if( $request->isMethod('post') ) { $this->formUser->bind($request->getParameter('sf_guard_user', array())); $this->formProfile->bind($request->getParameter('utilisateur', array())); if( $this->formUser->isValid() && $this->formProfile->isValid() ) { $con = Doctrine_Manager::connection(); try { $con->beginTransaction(); $newUser = $this->formUser->save($con); $newProfil = $this->formProfile->save($con); $newProfil->setUserId($newUser->getId()); $newProfil->save($con); $con->commit(); } catch(Exception $e) { $con->rollback(); throw $e; } $this->getUser()->setFlash('notice', "Votre inscription a bien été prise en compte.\nVous allez recevoir un email dans quelques minutes pour valider votre inscription."); $this->redirect('utilisateur/index'); } } }
Pour garantir l’intégrité des données il faut passer par une transaction que l’on est obligé de gérer à la main. (avec embedForm elle est gérée automatiquement) Le code html avec les deux formulaires :