Reputation: 46
I'm developing my first Zend Framework application with Doctrine2 and I can't make work a simple association. The editing works fine, but I can't get the creation of entities work properly.
My entities are these:
<?php
namespace Application\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
*/
class SpellListDetail{
/**
* @ORM\Id
* @ORM\ManyToOne(targetEntity="Application\Entity\SpellList", inversedBy="spellDetails")
* @ORM\JoinColumn(name="SpellList_id", referencedColumnName="id", nullable=false)
*/
private $sList;
/**
* @ORM\Id
* @ORM\ManyToOne(targetEntity="Application\Entity\Spell")
* @ORM\JoinColumn(name="Spell_id", referencedColumnName="id", nullable=false)
*/
private $spell;
/** @ORM\Column(type="integer") */
private $level;
/** @ORM\Column(type="float") */
private $areaValueOne;
/** @ORM\Column(type="float") */
private $areaValueTwo;
/** @ORM\Column(type="float") */
private $areaValueThree;
/** @ORM\ManyToOne(targetEntity="Application\Entity\AreaType") */
private $areaType;
/** @ORM\Column(type="boolean") */
private $areaLevel = false;
/** @ORM\Column(type="integer") */
private $durationValue;
/** @ORM\Column(type="integer") */
private $durationType;
/** @ORM\Column(type="integer") */
private $durationFail;
/** @ORM\Column(type="float") */
private $rangeValue = 0;
/** @ORM\Column(type="integer") */
private $rangeType;
/** @ORM\Column(length=2) */
private $primaryClass;
/** @ORM\Column(length=1) */
private $subClass;
/** @ORM\Column(type="boolean") */
private $instantaneous = false;
/** @ORM\Column(type="boolean") */
private $points = true;
//Setters & getter
<?php
namespace Application\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity (repositoryClass="Application\Repositories\SpellList")
*/
class SpellList{
const OPEN_LIST = 1000;
const CLOSED_LIST = 2000;
const EVIL_LIST = 3000;
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\Column(length=40)
*/
private $name;
/**
* @ORM\Column(type="text")
*/
private $description;
/**
* @ORM\ManyToOne(targetEntity="Application\Entity\Realm")
*/
private $realm;
/**
* @ORM\Column(type="integer")
*/
private $type;
/** @ORM\OneToMany(targetEntity="Application\Entity\SpellListDetail", mappedBy="sList", cascade={"persist", "remove"})
* @ORM\OrderBy({"level" = "ASC"})*/
private $spellDetails;
//Setters & getters
The third entity, Spell, is a simple entity with id, name and description, with no mapping because I'm trying to avoid unnecesary database calls
And this is the controller
public function createAction()
{
$form = new \Magic\Form\ListForm($this->model->getEntityManager());
$form->setAttribute('action', '/magic/list/create');
$spellList = new \Application\Entity\SpellList();
$form->bind($spellList);
if ($this->getRequest()->isPost()) {
$form->setData($this->getRequest()->getPost());
if ($form->isValid()){
foreach($spellList->getSpellDetails() as $detail){
$spell = $detail->getSpell();
if ($spell->getId() == null){
$this->model->getEntityManager()->persist($spell);
$this->model->getEntityManager()->flush();
}
}
$this->model->getEntityManager()->persist($spellList);
//$this->model->getEntityManager()->flush();
$this->model->getEntityManager()->flush();
}
}
$viewModel = new ViewModel(array('form' => $form));
$viewModel->setTemplate('magic/list/edit.phtml');
return $viewModel;
}
and I get the next error message
Entity of type Application\Entity\SpellListDetail has identity through a foreign entity Application\Entity\SpellList, 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 'Application\Entity\SpellListDetail'. 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.
So, if I understand the message, doctrine can't persist the whole association because he's trying to persist first the SpellListDetails than the SpellList and throws the Exception because SpellList has no id. I thought that this can be avoided with the mappedBy and persist options in Entity, so what I'm doing wrong?
Is any way to manually call the persist operation on the SpellList Entity before?
Thanks.
Upvotes: 1
Views: 579
Reputation: 7233
There are few mistakes here that i would point out striaght forward
your many side must have some thing like this which i believe is spelldetail
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
2ndly Remove ID clause from the same Entity which is detail (your code below)
/**
* @ORM\Id
* @ORM\ManyToOne(targetEntity="Application\Entity\SpellList", inversedBy="spellDetails")
* @ORM\JoinColumn(name="SpellList_id", referencedColumnName="id", nullable=false)
*/
private $sList;
/**
* @ORM\Id
* @ORM\ManyToOne(targetEntity="Application\Entity\Spell")
* @ORM\JoinColumn(name="Spell_id", referencedColumnName="id", nullable=false)
*/
private $spell
Change it to
/**
* @ORM\ManyToOne(targetEntity="Application\Entity\SpellList", inversedBy="spellDetails")
* @ORM\JoinColumn(name="SpellList_id", referencedColumnName="id", nullable=false)
*/
private $sList;
/**
* @ORM\ManyToOne(targetEntity="Application\Entity\Spell",inversedBy="spellDetails")
* @ORM\JoinColumn(name="Spell_id", referencedColumnName="id", nullable=false)
*/
private $spell
WHat you need to know is that when there is relation and if relation is correct Doctrine will acutoatically map relation for foregin keys along with constraints.
Also you missed
inversedBy="spellDetails"
with your relation with spell entity and i have placed that in the edited code.I am only answering in refrence to actuall question which was associations. I havent seen your controller yet so if you experience a problem persisting/Flush (saving data) comment below
Upvotes: 3