Archives


Master Symfony2 fundamentals

Be trained by SensioLabs experts (2 to 6 day sessions -- French or English).
trainings.sensiolabs.com

Symfony hosting done right

ServerGrove, outstanding support at the right price for your Symfony hosting needs.
servergrove.com

L'audit Qualité par SensioLabs

200 points de contrôle de votre applicatif web.
audit.sensiolabs.com

Fabien Potencier
New in symfony 1.2: God save the nested forms
by Fabien Potencier – November 05, 2008 – 21 comments

In symfony 1.1, we introduced a new form sub-framework. It is a great step forward for symfony, even if the learning curve is a bit steep.

We worked a lot to make it even better for symfony 1.2, and more importantly simpler for newcomers.

One of the form framework strengths is its ability to deal with nested forms. A form can embed a form which in turn can also embed another form (and so on):

$article = ArticlePeer::doSelectOne(new Criteria());
 
$articleForm = new ArticleForm($article);
$authorForm = new AuthorForm($article->getAuthor());
$companyForm = new AuthorForm($article->getAuthor()->getCompany());
 
$authorForm->embedForm('company', $companyForm);
$articleForm->embedForm('author', $authorForm);
 

The articleForm renders as show below:

Embedded forms

Another great feature of the form framework is its ability to automatically serialize forms. As the forms above are Propel ones, a simple call to $articleForm->save() will automatically update the $article object with the submitted and validated values and save it back to the database.

But there was a problem in symfony 1.1. The author and the company objects were not saved automatically. So, you had to override the save() method to get the validated data and update the objects manually. Nothing impossible to do, but really annoying as the form framework already had all the needed information to make it automatic.

This has been implemented in symfony 1.2 and so will be available with the upcoming beta 2. That's right, a single call to $form->save() will now update the article, the author, and the company objects. That's a great news by itself, but there is another one: The new admin generator also takes this new feature into account.

Add a Comment

You must be connected to post a comment.

Comments RSS

  • gravatar
    #1 Stephen Ostrow said on the 2008/11/05 at 20:51
    I don't know if this stems directly from my post in the groups requesting this or not, but I just wanted to be the first to thank you for this and hope that I'm not the only one helped greatly.
  • gravatar
    #2 Fabien said on the 2008/11/05 at 20:54
    @Stephen Ostrow: I was more than embarrassed by this issue. It was the result of an oversight and I am the very first one to be more than happy that it is fixed now. I am sure it will help a lot of people.

  • gravatar
    #3 pppswing said on the 2008/11/05 at 20:57
    Please, Fabien can you do a tutorial how to do a project with DoctrinePlugin with few classes and explaining the "recommended" practises to build the Database.

    Because there are a lot of possibilities with Doctrine and It's easy to get paralyzed.
  • gravatar
    #4 Stephen Ostrow said on the 2008/11/05 at 21:03
    @Fabien: No need to be embarrassed. I think a lot of people were waiting for 1.2 to make the switch, and now that it's getting closer the new framework is going to get a lot more interest. It looks like it will be very useful and save lots of time.

    Is it better practice to put the embedForm in the form class or do it in the action. I had found the function initially, but I have it in a new form class and I can't figure out if that's what is causing validation issues.
  • gravatar
    #5 Ken Marfilla said on the 2008/11/05 at 21:43
    How about handling one to many relationship such as Article -> Authors?

  • gravatar
    #6 Éric Rogé said on the 2008/11/05 at 21:53
    Hello Fabien,

    This post comes at a perfect time for me, I've tried to use this feature on a brand new project, but I have to deal with an issue that many users may have to face on their own project.


    On my Article form, I've added an author embeded form, but only on the purpose to add an new author.

    So I have 3 important fields on my form:

    - A select field with the existing authors
    - A checkbox "Add a new Author" that I've added
    - An empty author form, to add a new Author

    Here is the comportment that I want to have :

    if "Add a new Author" is checked
    I have to desactivate the validator on the existing authors select field
    And then save the new Author, and link it to the article
    else
    I have to desactivate the "new Author" embeded form
    And handle the basic existing authors field

    Thanks to sfValidatorCallback, I know that I can ADD some custom validators depending on the values submited.

    But how can I properly DISABLE some validators depending on the "Add a new author" checked test ?

    I know that this comment might seem confused, so here is the form topic that I've created n this subject, with screenshots and source code.
  • gravatar
    #7 Fabien said on the 2008/11/05 at 21:54
    @Stephen Ostrow: It is better to put everything in the form class directly for better reusability.
  • gravatar
    #8 Éric Rogé said on the 2008/11/05 at 21:55
    Oups, I've forgotten to add the link, here it is : http://www.symfony-project.org/forum/index.php/t/16502/
  • gravatar
    #9 sh1ny said on the 2008/11/05 at 22:21
    Is this working for Doctrine forms also ? I can't check it right now.
  • gravatar
    #10 Stephen Ostrow said on the 2008/11/05 at 23:49
    Fabien: That's what I would assume, but that's where i run into validation errors. I'm trying to embed multiples of Form X in Form Y, in your example many Authors in your Article form. Could you add an example of using the naming function for something like that.

    sh1ny: Yes this works for Doctrine as well. I've just noticed in 1.1 you have to manually run doctrine:build-forms app. In 1.2 it will automatically build forms, filters, and models while running doctrine:build-all
  • gravatar
    #11 John said on the 2008/11/06 at 00:37
    This is cool and I believe is a much needed feature.
    Does this work for merged forms as well?
  • gravatar
    #12 Guillaume Chanaud said on the 2008/11/06 at 01:56
    Thank for this ! I had 'lots of fun' with multiple embedded forms in symfony 1.1, i will be definitively be better in 1.2 !
  • gravatar
    #13 Darmen said on the 2008/11/06 at 05:34
    Hi Fabien!
    How we can approach this when using Admin Generator?
  • gravatar
    #14 Jérôme Vieilledent said on the 2008/11/06 at 08:53
    Great news, thanks !
    Will it be possible to dynamically add fields ? For example, when you have to edit an invoice, you can have a variable number of lines which may be added dynamically via JS.
    For the moment, in my Symfony 1.1 project, I treat my lines as separate forms and I "link" them with my array of Propel line objects (they are linked with the same array index).
    This solution works but it doesn't appear reliable to me. It would be appreciable to have a built in solution for that...
    Thx
  • gravatar
    #15 Arne said on the 2008/11/06 at 08:56
    well, with sf 1.1 and Doctrine this already worked or not ?
    I have used embedded forms and the embedded objects were also saved by doctrine
  • gravatar
    #16 Matthias said on the 2008/11/06 at 09:08
    @Arne: this is because Doctrine itself is able to save all related records you add/edit automatically while it seems Propel is not
  • gravatar
    #17 vincent said on the 2008/11/06 at 17:57
    syntax error ?
    I think :

    $companyForm = new AuthorForm($article->getAuthor()->getCompany());

    should be :

    $companyForm = new CompanyForm($article->getAuthor()->getCompany());

    Great feature this nested thing !
  • gravatar
    #18 Haghen said on the 2008/11/06 at 19:34
    Can we use the sfForm's 1.2 implementation into 1.1 symfony's core ?
  • gravatar
    #19 Fabien said on the 2008/11/06 at 21:04
    @Haghen: Yes, it is possible. But for sfFormPropel to work properly, you will also need to upgrade to Propel 1.3 as some signature have changed.
  • gravatar
    #20 jwage said on the 2008/11/07 at 02:55
    @sh1ny Yes. This all works the same with Doctrine. I will publish an article that demonstrates all the same functionality very soon.

    @Arne Yes this already worked with Doctrine. It was a side affect of how Doctrine handles relationships when using the $object->fromArray() method and propel doesn't.
  • gravatar
    #21 Fabien said on the 2008/11/07 at 06:51
    @ALL: we will publish a real world example on Monday. So, stay tuned. In the meantime, read the post on Doctrine implementation... Jon did an amazing job so that Propel and Doctrine are now on par.