Symfony2用关系实体持久化表单集合


Symfony2 Persisting form collection with a relational entities

通过研究还没有找到解决这个问题的方法,但我正试图将两种形式保存到数据库中(嵌入式/集合)。我有彼此相关的实体,我希望表单提交并将这两个实体持久化到数据库中。

主体:

/**
 * @var integer
 * @ORM'OneToMany(targetEntity="Sub", mappedBy="mainId", cascade={"persist"})
 */
protected $sub;
public function __construct() {
    $this->sub = new ArrayCollection();
}

子实体:

 /**
 * @var integer
 *
 * @ORM'Column(name="main_id", type="integer")
*/
protected $mainId;
.......
  /**
 * @ORM'ManyToOne(targetEntity="Main", inversedBy="sub")
 * @ORM'JoinColumn(name="main_id", referencedColumnName="id")
 */
protected $main;
下面是我的MainType表单:

class MainType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('dano', 'text', array(
                'label' => 'DA: ',
                'disabled' => true
            ))
        ->add('partno','text', array(
                'label' => 'Part: ',
                'disabled' => true
            ))
        ->add('batchno', 'text', array(
                'label' => 'Batch: ',
                'disabled' => true
            ))
        ->add('sub', 'collection', array('type' => new SubType()))
        ->add('submit', 'submit');
}......

和SubType表单:

class SubType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('main_id','hidden')
        ->add('rackno','text', array(
                'label' => 'Rack No(s) '
            ))
        ->add('diecode','text', array(
                'label' => 'Die Code '
            ))
        ->add('heatcode','text', array(
                'label' => 'Heat Code '
            ))
        ->add('inqty','integer', array(
                'label' => 'Qty In '
            ))
        ->add('onhold','choice', array(
                'label' => 'Hold',
                'choices' => array(
                    '1' => 'On Hold',
                    '0' => 'Released'
                ),
                'multiple' => false,
                'expanded' => true
            ));

我的控制器:

/**
 * @param Request $request
 * @Route("/{dano}", name="subpart_part")
 */
public function submitPartByDAAction(Request $request, $dano) {
    $em = $this->getDoctrine()->getManager();
    $entity = $em->getRepository('Bundle:Main')
        ->findOneByDano($dano);
    $partno = $entity->getPartno();
    $batchno = $entity->getBatchno();
    $mainid = $entity->getId();

    $main1 = new Main();
    $main1->setDano($dano);
    $main1->setPartno($partno);
    $main1->setBatchno($batchno);
    $sub1 = new Sub();
    $sub1->setMainId($mainid);
    $main1->getSub()->add($sub1);
    $form = $this->createForm(new MainType(), $main1, array(
            'method' => 'POST'
        ));
    $form->handleRequest($request);
    if($form->isValid()) {
        $em = $this->getDoctrine()->getManager();
            $em->persist($main1);
            $em->flush();
        return $this->redirect($this->generateUrl('subpart_home'));
    }
    return $this->render('Bundle:Parts:addparts.html.twig', array(
            'form' => $form->createView()
        ));
}

让我解释一下我在这里做了什么,起初我没有Sub的"main_id"字段(这与Main的id相关),但当我尝试持久化数据时,它给了我错误:

An exception occurred while executing 'INSERT INTO sub 
(main_id, rackno, heatcode, diecode, inqty, onhold) VALUES 
(?, ?, ?, ?, ?, ?)' with params [null, "46", "eterte", "seteter", 3, 0]:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 
'main_id' cannot be null

所以我做了一个字段"main_id"与它被隐藏,从主抓取id getId();并将它传递给subform的setMainId();要坚持,它仍然给我相同的错误,"main_id"不能为空。

我错过了什么?谢谢!

您的实体定义错误。首先理解ORM和关系的概念。您的Sub实体不需要有整数main_id。只需将其映射到Main实体。您的Main实体应该看起来像

/**
 * @var Sub 
 * this value is just integer in database, but doc should point it to Sub
 * @ORM'OneToMany(targetEntity="Sub", mappedBy="mainId", cascade={"persist"})
 */
protected $sub;
public function __construct() {
    $this->sub = new ArrayCollection();
}

和你的Sub实体

/**
 * @ORM'ManyToOne(targetEntity="Main", inversedBy="sub")
 * @ORM'JoinColumn(name="main_id", referencedColumnName="id")
 */
protected $main;

不需要main_id。ORM会帮你处理的。MainType表格很好。只要去掉SubType形式的main_id。

你应该通过对象而不是它们的id来引用实体。在控制器中,而不是使用

$sub1->setMainId($mainid);

你应该设置对象。

$sub1->setMain($main1);

你的主表单也有点奇怪。我并不是说它无效,但是你应该考虑替换这一行:

->添加("子"、"收藏",数组('类型' =>新的亚型()))

像这样:

->add('sub', new SubType(), array())

我认为如果你只有"一件"物品会更合适。当需要很多项时,可以使用collection。

我建议您查看表单组件…如何将表单表示为树…

也永远不要让字段像"main_id",除非是必要的。尽量不要使用id,而是使用关联。