如何使用固定子表单创建symfony2表单集合

时间:2015-07-22 11:56:31

标签: symfony doctrine

我正在尝试创建一个表单来收集设施和联系信息列表:

问题是我想拥有这个设施,以及4个不同类型的联系人。我意识到我可以通过使每个联系人成为Facility实体上的属性来单独完成这项工作,但如果它在一个集合中,感觉它将更加清晰,更容易使用它。

你会注意到在FacilityType类中,我使用$ builder-> create来添加一个子表单,它给出了我期望的结构,但是当我尝试持久化时出现错误。 “通过关系'AppBundle \ Entity \ Facility#contacts'找到了一个新的实体,它没有配置为级联实体的持久化操作:......”

感谢。我的代码如下。

工厂实体:

<?php 
namespace AppBundle\Form;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
class Facility
{
  /**
   * @ORM\Column(length=200)
   */
  public $name;
  /**
   * @ORM\OneToMany(targetEntity="FacilityContact", mappedBy="facility")
   */
  public $contacts;
  public function __construct()
  {
    $this->contacts = new ArrayCollection;
  }
}

FacilityContact实体:

<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
class FacilityContact
{
  /**
   * @ORM\ManyToOne(targetEntity="facility", inversedBy="contacts")
   */
  public $facility;
  /**
   * @ORM\Column(type="string", length=50)
   */
  public $contactType;
  /**
   * @ORM\Column(type="string", length=200)
   */
  public $name;
  /**
   * @ORM\Column(type="string", length=100)
   */
  public $email;
  /**
   * @ORM\Column(type="string", length=15)
   */
  public $phone;
}

设施表格     

class FacilityType extends AbstractType
{
  /**
   * @param FormBuilderInterface $builder
   * @param array $options
   */
  public function buildForm(FormBuilderInterface $builder, array $options)
  {
    $centre = $this->centre;
    $builder->add('name', 'text', array("label"=>"Facility Name");

    $contacts = $builder->create("contacts", "form");
    $contacts
      ->add("radonc", new FacilityContactType("radonc"), array("label" => "Radiation Oncologist"))
      ->add("physicist", new FacilityContactType("physicist"), array("label" => "Physicist Responsible"))
      ->add("radtherapist", new FacilityContactType("radtherapist"), array("label" => "Radiation Therapists"))
      ->add("datamanager", new FacilityContactType("datamanager"), array("label" => "Data manager"))
      ;        
    $builder->add($contacts);
  }
  public function setDefaultOptions(OptionsResolverInterface $resolver)
  {
    $resolver->setDefaults(array(
      'data_class' => 'AppBundle\Entity\Facility'
    ));
  }
  public function getName()
  {
     return 'appbundle_facility';
  }
}

FacilityContact表单

<?php
namespace AppBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class FacilityContactType extends AbstractType
{
  private $contactType;
  public function __construct($contactType)
  {
    $this->contactType = $contactType;
  }
  /**
   * @param FormBuilderInterface $builder
   * @param array $options
   */
  public function buildForm(FormBuilderInterface $builder, array $options)
  {
    $builder
      ->add('contactType', 'hidden', array("read_only" => true, "data"=>$this->contactType))
      ->add('name', 'text', array("required" => false))
      ->add('phone', 'text', array("required" => false))
      ->add('email', 'email', array("required" => false))
    ;
  }

  /**
   * @param OptionsResolverInterface $resolver
   */
  public function setDefaultOptions(OptionsResolverInterface $resolver)
  {
    $resolver->setDefaults(array(
      'data_class' => 'AppBundle\Entity\FacilityContact'
    ));
  }
  /**
   * @return string
   */
  public function getName()
  {
    return 'appbundle_facilitycontact';
  }
}

1 个答案:

答案 0 :(得分:0)

Doctrine试图告诉你,有一个或多个对象,它们不知道,因为它们没有持久存储到数据库中。

这种情况发生了,因为在FacilityForm中您正在使用FacilityContactForm,它创建了4个新的FacilityContact实体。您试图仅在没有其他4个实体的情况下保留Facility实体,这不会有任何问题,但它们之间存在关系,并且在数据库中,Facility实体没有其FacilityContacts。

您可以通过两种方式解决此问题:

  • 使用级联选项,如下所示:@ORM\OneToMany(targetEntity="FacilityContact", mappedBy="facility", cascade={"persist"}),基本上这告诉学说它应该还存在于FacilityContacts实体中,你可以在http://doctrine-orm.readthedocs.org/en/latest/reference/working-with-associations.html阅读更多信息,你也可以这里有关于级联的一些解释:Doctrine Cascade Options for OneToMany

  • 另一种选择是在联系人集合为空的Facility实体之前创建,将其持久保存到数据库,然后将FacilityContacts持久保存到数据库并使用add方法将它们添加到联系人数组中,然后只调用$ em-&gt; update(),因为doctrine知道并监控有关Facility实体的任何更改。