开发者

Zend+Doctrine2: How do I flush correctly an entity with ArrayCollections()?

I am starting my first Zend Framework + Doctrine 2 project and I have a question. I use PostgreSQL 9 and Apache 2.2 I have the following entities (the names of the entities and attributes are just for this example):

<?php
namespace Xproject\Entities;
/**
 * Entity1   
 * @Table()  
 * @Entity  
 */      
class Entity1
{  
/***  
 * @var integer $ent1Code     
 * @Column(name="ent1Code", type="integer", length=4)  
 * @Id  
 * @GeneratedValue(strategy="IDENTITY")  
 */  
private $ent1Code;

/**
 * @var decimal $att1     
 * @Column(name="att1", type="decimal")
 */
private $att1;

 /** 
 * OWNING SIDE
 * @var \Doctrine\Common\Collections\ArrayCollection     
 * @ManyToOne(targetEntity="Entity2", inversedBy="entity1")
 * @JoinColumn(name="ent2Code", referencedColumnName="ent2Code")
 */
private $entity2;

/** 
 * UNIDIRECTIONAL
 * @var \Doctrine\Common\Collections\ArrayCollection
 * @ManyToOne(targetEntity="Entity3")
 * @JoinColumn(name="ent3Code", referencedColumnName="ent3Code")
 */
private $entity3;

 /**
 * UNIDIRECTIONAL
 * @var \Doctrine\Common\Collections\ArrayCollection
 * @ManyToOne(targetEntity="Entity4")
 * @JoinColumn(name="ent4Code", referencedColumnName="ent4Code")
 */
private $entity4;

public function __construct() {
    $this->entity2 = new \Doctrine\Common\Collections\ArrayCollection();
    $this->entity3 = new \Doctrine\Common\Collections\ArrayCollection();
    $this->entity4 = new \Doctrine\Common\Collections\ArrayCollection();
}

public function getEnt1Code(){
    return $this->ent1Code;
}

public function getAtt1(){
    return $this->att1;
}

public function setAtt1($value){
    $this->att1=$value;
}

public function addEntity2(Entity2 $value){
    $value->addEntity1($this);
    $this->entity2->add($value);
}

public function addEntity3(Entity3 $value){
    $this->entity3->add($value);
}

public function addEntity4(Entity4 $value){
开发者_Go百科    $this->entity4->add($value);
  }  
}

<?php
namespace Xproject\Entities;
/**
 * Entity2 
 * @Table()
 * @Entity
 */
class Entity2
 {
/**
 * @var integer $ent2Code     
 * @Column(name="ent2Code", type="integer", length=4)
 * @Id
 * @GeneratedValue(strategy="IDENTITY")
 */
private $ent2Code;

/**
 * INVERSE SIDE
 * @var entity1    
 * @OneToMany(targetEntity="Entity1", mappedBy="entity2")
 */
private $entity1;

public function __construct() {
    $this->entity1 = new \Doctrine\Common\Collections\ArrayCollection();
}

public function getEnt2Code(){
    return $this->ent2Code;
}

public function addEntity1(Entity1 $value){
    $this->entity1->add($value);
}
}

<?php
namespace Xproject\Entities;

/**
 * Entity3
 * @Table()
 * @Entity
 */
class Entity3
{
/**
 * @var integer $ent3Code     
 * @Column(name="ent3Code", type="integer", length=4)
 * @Id
 * @GeneratedValue(strategy="IDENTITY")
 */
private $ent3Code;

/**
 * @var string $att1     
 * @Column(name="att1", type="string", length=150)
 */
private $att1;

public function getEnt3Code(){
    return $this->ent3Code;
}

public function getAtt1(){
    return $this->att1;
}

public function setAtt1($value){
    $this->att1=$value;
}

}

<?php   
namespace Xproject\Entities;
/**
 * Entity4 
 * @Table()
 * @Entity
 */
 class Entity4 
{
/**
 * @var integer $ent4Code   
 * @Column(name="ent4Code", type="integer", length=4)
 * @Id
 * @GeneratedValue(strategy="IDENTITY")
 */
private $ent4Code;

/**
 * @var string $att1    
 * @Column(name="att1", type="string", length=150)
 */
private $att1;

public function getEnt4Code(){
    return $this->ent4Code;
}

public function getAtt1(){
    return $this->att1;
}

public function setAtt1($value){
    $this->att1=$value;
}
}

Just to try if everything is working I use the following code in Xproject's indexController:

<?php
class IndexController extends Zend_Controller_Action
{
    public function init()
   {
        $this->doctrine = Zend_Registry::get('doctrine');
        $this->em = $this->doctrine->getEntityManager();
    }

public function indexAction()
{
    $ent2 = new Xproject\Entities\Entity2();
    $this->em->persist($ent2);

    $ent3 = new Xproject\Entities\Entity3();
    $ent3->setAtt1('xyz');
    $this->em->persist($ent3);

    $ent4= new Xproject\Entities\Entity4();
    $ent4->setAtt1('abc');
    $this->em->persist($ent4);

    //1st flush
    $this->em->flush();                       

    $ent1= new Xproject\Entities\Entity1();
    $ent1->setAtt1(350.00);
    $ent1->addEntity2(ent2);
    $ent1->addEntity3(ent3);
    $ent1->addEntity4(ent4);
    $this->em->persist($ent1);

    //2nd flush
    //$this->em->flush();     
}
}

The first flush works OK and everything is saved OK into the database, but if I use both the first and the second flush, the browser indicates an Application Error and $ent1 is not saved at all into the database.

Using a var_dump($ent1) I can see that the object $ent1 state is correct (att1 and all the collections are loaded OK).

Apache error log doesn't show any error or warning during the loading of this script.

I definitely think I am missing some important thing here related to the ArrayCollections and how they work when you flush them.

Am I missing something crucial?


Your relationships are all ManyToOne, so there should be no ArrayCollections involved.

Since there are no collections, you don't want to add stuff, you want to set stuff:

In Entity1:

public function setEntity2(Entity2 $entity2){
    $this->entity2 = $entity2
    return $this;
}

In your controller:

$entity1->setEntity2($entity2);

And that's it. Your calls like $this->entity2->add() are working, because you're initializing those properties as ArrayCollections. But doctrine is just ignoring them.

In other words, for a *ToOne relationship, the object properties are just the foreign entity type. Treat them like simple values, and set them via typical set*() mutator.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜