简体   繁体   中英

How do I display data for an embedded object in an embedded form using Silex and Symfony Forms?

I have a model in my application called Content . This has three properties that are linked to another model called ContentBodyType . This is to allow three sections of the content which are 'Banner', 'Summary' and 'Main'.

I have created a FormType for the Content model using SymfonyForms. The following shows how this is built up:

public function buildForm(FormBuilderInterface $builder, array $options) {

    $list = $this -> app['model.collection'] -> getList();

    $builder -> add('id', HiddenType::Class)
             -> add('displayname', TextType::Class, array("label" => "Friendly Name", "trim" => true))
             -> add('description', TextareaType::Class)
             -> add('collection', ChoiceType::Class, array(
               'choices_as_values' => true,
               "choices" => $list,
               "label" => "Collection"
             ))
             -> add('publish', ChoiceType::Class, array(
               "choices" => array('Yes' => true, 'No' => false),
               "choices_as_values" => true,
               "expanded" => true,
               "multiple" => false,
             ))
             -> add('homepage', ChoiceType::Class, array(
               "choices" => array('Yes' => true, 'No' => false),
               "choices_as_values" => true,
               "expanded" => true,
               "multiple" => false,
             ))
             -> add('startdate', DateTimeType::Class, array("widget" => "single_text", "format" => "dd-MM-yyyy"))
             -> add('expirydate', DateTimeType::Class, array("widget" => "single_text", "format" => "dd-MM-yyyy"))
             -> add('type', ChoiceType::Class, array(
               "choices_as_values" => true,
               "choices" => array(
                 'News' => "news",
                 'Page' => "page",
                 'Pinned' => "pinned",
                 'Blog' => "blog",
                 'Slider' => "slider"
               ),
               "label" => "Type"
             ))
             -> add('main', new \Turtle\Form\Type\ContentBodyType())
             -> add('banner', new \Turtle\Form\Type\ContentBodyType())
             -> add('summary', new \Turtle\Form\Type\ContentBodyType())
             -> add('save', SubmitType::Class)
             -> add('cancel', ButtonType::Class);

    // only add the name field if this is a new template
    if (!$this -> content || null == $this -> content -> getId()) {
      $builder -> add('name', TextType::Class, array('label' => 'Name'));
    }
  }

When the application loads up the form it shows the data from Content model in the correct fields, however the ones that are part of the nested form are not displayed.

Now I know that this is because for each of 'banner', 'summary' and 'main' I am creating a new instance of the ContentBodyType form object. However I cannot work out how to pass in the object to this so that it does not have to be created.

The form is created using the following code:

   public function edit(Request $request, $id) {

     // Get the entity from the datastore for the specified id
     if ($id == "new") {
       $item = new \Turtle\Model\Entity\Content(); 
     } else {
       $item = $this -> app['model.content'] -> getById($id) -> first();
     }

     if (!$item) {
       return "notthere";
     }

     // Build the form
     $type = new \Turtle\Form\Type\ContentType($this -> app, $item);

     $form = $this -> app['form.factory'] 
                   -> createBuilder(
                         $type, 
                         $item, 
                         array(
                           'action' => $this -> app['url_generator'] -> generate(
                             'content_update', 
                             array(
                               'id' => $item -> getId()
                             )
                           )
                         )
                       ) -> getForm();

     // process the form to see if it has been submitted or not
     $form -> handleRequest($request);

     snip ....

I am sure that this is a simple fix, but I just cannot see what it is.

Thanks, Russell

I have worked this out. I had forgotten that when I create an instance of the ContentBody I made the constructor accept arguments one of which was the item that had been loaded from the datastore.

class ContentType extends AbstractType {

  private $app;
  private $item;

  public function __construct($app, $item) {
    $this -> app = $app;
    $this -> item = $item;
  }

  snip....

So as I have the item as a property in the class, I can then pass this to the ContentBodyType in the buildForm function. So now the three sections of the form get created thus:

-> add('main', new \Turtle\Form\Type\ContentBodyType($this -> item -> getBanner()))
-> add('banner', new \Turtle\Form\Type\ContentBodyType($this -> item -> getSummary()))
-> add('summary', new \Turtle\Form\Type\ContentBodyType($this -> item -> getMain()))

I am not sure if this is the correct way to do it because I am sure that at some point in the SymfonyForms code the model is passed to the FormType, but this solved the issue I had.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM