dongyijing2353
2014-07-29 21:10
浏览 48
已采纳

无法在Symfony2 / Doctrine2中保留复杂的实体图

I'm a bit limited in the details I can provide due to a NDA, so please bear with me.

I have a complex entity graph. It consists of:

  • A 1-to-1 relationship between a Parent and Child.
  • The Child contains an ArrayCollection of FooChild entities. Cascade all.
  • FooChild represents a many-to-many join table between Foo and Child, but also contains some metadata that Child needs to track. Cascade persist on each side (Foo and Child)
  • Parents aren't required to have a Child.

To be 100% clear regarding FooChild, the relationship is many-to-many, but because of the metadata, it contains many-to-one relationship definitions:

/**
 * @ORM\Entity
 * @ORM\Table(name="foo_children", indexes={
 *      @ORM\Index(name="fooid_idx", columns={"foo_id"}),
 *      @ORM\Index(name="childid_idx", columns={"child_id"}),
 * })
 */

class FooChild
{
    /**
     * @ORM\Id()
     * @ORM\ManyToOne(targetEntity="Foo", cascade={"persist"})
     * @ORM\JoinColumn(name="foo_id", referencedColumnName="id", nullable=false)
     */
    protected $foo;

    /**
     * @ORM\Id()
     * @ORM\ManyToOne(targetEntity="Child", inversedBy="fooChildren", cascade={"persist"})
     * @ORM\JoinColumn(name="child_id", referencedColumnName="id", nullable=false)
     */
    protected $child;

    /**
     * @ORM\Column(type="smallint")
     */
    private $count;

    // methods
}

Okay, so with that structure, on the Parent edit page, I created the option for someone to add a Child to it and populate it with FooChilds with the Symfony prototype mechanism seen here. When I attempt to submit the rather large form, I get the following exception:

Entity of type MyBundle\Entity\FooChild has identity through a foreign entity MyBundle\Entity\Child, however this entity has no identity itself. You have to call EntityManager#persist() on the related entity and make sure that an identifier was generated before trying to persist 'MyBundle\Entity\FooChild'. In case of Post Insert ID Generation (such as MySQL Auto-Increment or PostgreSQL SERIAL) this means you have to call EntityManager#flush() between both persist operations.

The thing is, I've attempted to persist the various parts of this graph in different orders, and the exception still remains. My current attempt is:

$form = $this->createForm(new ParentType(), $parent);

if ($request->getMethod() == 'POST') {
    $form->handleRequest($request);

    if ($form->has('child')) {
        $data = $form->getData();
        $child = $data->getChild();
        $fooChildren = $child->getFooChildren();

        foreach ($fooChildren as $fc) {
            $em->persist($fc);
            $em->flush();
        }

        $em->persist($child);
        $em->flush();
    }

    $em->persist($parent);
    $em->flush();
}

The exception is thrown at the first attempt to persist, in the foreach. Like I said before, I've swapped the order of what gets persisted when several times, but it hasn't made a difference. I'm not sure what else to try.

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • doulu4534 2014-07-30 20:59
    已采纳

    I had an initial solution of removing the Child's form type and having the Parent's form type handle unmapped (very important) FooChild entries. Then, in the controller, I had:

    $em->persist($parent);
    $em->flush();
    
    if ($form->has('fooChildren')) {
        $child = new Child();
        $child->setParent($parent);
    
        $em->persist($child);
        $em->flush();
    
        // run through the FooChild entites and add them to the child
    }
    

    It worked, but I ran into some other non-related issues, so I'm currently reorganizing my schema.

    点赞 打赏 评论

相关推荐 更多相似问题