Symfony&学说:在嵌入式表单集合中持久存储多个实体

时间:2014-05-06 22:28:37

标签: php forms symfony doctrine-orm

目前有点咸菜。我有2个实体:Main和Sub,它是一个OneToMany关系(一个main可以有很多subs)我创建了一个嵌入在一起的表单集合。我首先有一个搜索表单,用户可以通过其中一个属性搜索Main,然后将它们发送到一个页面,其中有一个包含搜索到的Main的表单,其属性列在表单上但被禁用,因此用户无法编辑它们,已启用的字段来自嵌入的子表单,用户需要输入该表单才能提交。

1)用户通过其属性搜索Main,即“pono”(PO编号)
2)用户被重定向到一个页面,该页面显示他/她使用列出的(pono),(cano),(bano)搜索的行 - 它被禁用,因此无法编辑 3)启用的字段为空,用户必须输入将提交到Sub实体的信息。

在我的主要实体

 /**
 * @var Sub
 * @ORM\OneToMany(targetEntity="Sub", mappedBy="mainId")
 */
protected $sub;

public function __construct() {
    $this->sub = new ArrayCollection();
}

我的Sub实体:

 /**
 * @var integer
 *
 * @ORM\Column(name="main_id", type="integer")
*/
protected $mainId;

 /**
 * @ORM\ManyToOne(targetEntity="Main", inversedBy="sub", cascade={"persist"})
 * @ORM\JoinColumn(name="main_id", referencedColumnName="id")
 */
protected $main;

以我的主要形式:

 public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('pono', 'text', array(
                'label' => 'PO: ',
                'disabled' => true
            ))
        ->add('cano','text', array(
                'label' => 'CA: ',
                'disabled' => true
            ))
        ->add('bano', 'text', array(
                'label' => 'BA: ',
                'disabled' => true
            ))
        ->add('sub', 'collection', array('type' => new SubType()));
}

在我的子表格中:

 public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('qty','integer', array(
                'label' => 'Qty: '
            ))
        ->add('location','text', array(
                'label' => 'Location: '
            ))
        ->add('priority','text', array(
                'label' => 'Priority: '
            ));
}

所以在我的控制器上

 public function submitItemAction(Request $request, $pono) {
    $em = $this->getDoctrine()->getManager();
    $entity = $em->getRepository('ItemBundle:Main')
        ->findOneByPono($pono);

    $cano = $entity->getCano();
    $bano = $entity->getBano();

    $main = new Main();
    $main->setPono($pono);
    $main->setCano($cano);
    $main->setBano($bano);

    $sub = new Sub();
    $sub->setMain($main);
    $main->getSub()->add($sub);

    $form = $this->createForm(new MainType(), $main, array(
            'method' => 'POST'
        ))
        ->add('submit','submit');

    $form->handleRequest($request);
    if($form->isValid()) {
        $em = $this->getDoctrine()->getManager();
        $em->persist($sub);
        $em->flush();

        return $this->redirect($this->generateUrl('success'));

    }

现在提交时,它正在提交BOTH Main和Sub。它给了我一个重复的Main和新添加的Sub。我知道这是它应该做的,但我需要它只提交Sub。我尝试使用id从Main检索$mainid = $entity->getId();并将其放入$sub->setMainId($mainid),然后我不断收到main_id不能为空的错误消息。

任何接受者? 编辑:Twig模板:

{{ form_start(form) }}
            {{ form_label(form.pono) }}
            {{ form_widget(form.pono) }} <br>

            {{ form_label(form.cano) }}
            {{ form_widget(form.cano) }}<br>

            {{ form_label(form.bano) }}
            {{ form_widget(form.bano) }} <br>

            {% for sub in form.sub %}
                {{ form_label(sub.qty) }}
                {{ form_widget(sub.qty) }} <br>

                {{ form_label(sub.location) }}
                {{ form_widget(sub.location) }} <br>

                {{ form_label(sub.priority) }}
                {{ form_widget(sub.priority) }}<br>

            {% endfor %}
        {{ form_widget(form.submit) }}
        {{ form_end(form) }}

1 个答案:

答案 0 :(得分:2)

在查看您的代码后,我认为可以使其工作,您需要修复一些事项。我将在几个步骤中编辑此答案。在开始更改代码之前,还要备份/提交代码。

1)在MAIN实体中(添加级联持久性)

 /**
 * @var Sub
 * @ORM\OneToMany(targetEntity="Sub", mappedBy="main", cascade={"persist"}) 
 */
protected $sub;

2)SUB实体:

删除受保护的$ mainId;它的注释。

从ManyToOne

中删除cascade = {&#34; persist&#34;}

3)看看你的控制器动作。

$sub = new Sub();
$sub->setMain($main);
$main->getSub()->add($sub);

注意setMain()方法。您不希望在控制器中执行此操作,而是在实体中自动执行此操作。此外,您应该手动添加到集合,但为它创建一个方法。所以你只会这样:

$sub = new Sub();
$main->addSub($sub);

4)在MAIN实体添加(您可能需要导入Sub):

public function addSub(Sub $sub) {
    $sub->setMain($this);
    $this->sub->add($sub);
    return $this;
}

您还应该添加其他方法,如removeSub(),removeSub(),getSub()。 getSub()返回集合,而前两个将返回$ this。

5)控制器

不要坚持Sub,而是坚持。 (学说将级联持续到Sub)

$em->persist($main);

6)您需要添加&#39; by_reference&#39;主要表格类型中的子集合选项。

->add('sub', 'collection', array('type' => new SubType(), 'by_reference' => false));

这将调用实际的addSub()方法,而不是直接调用add方法。

7)我不知道你为什么在下面建立一个新的主要实体。

$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('ItemBundle:Main')
    ->findOneByPono($pono);

$cano = $entity->getCano();
$bano = $entity->getBano();

$main = new Main();
$main->setPono($pono);
$main->setCano($cano);
$main->setBano($bano); 

尝试更改为:

$em = $this->getDoctrine()->getManager();
$main = $em->getRepository('ItemBundle:Main')
    ->findOneByPono($pono);

您可能应该将Pono定义为唯一。