Reputation: 711
I am creating the primary key (string) for an entity, and I'm trying to update it. However when I call $em->persist() and then $em->flush() Doctrine tries to INSERT a new record instead of updating the currently existing one.
Entity:
/**
* @Entity @Table(name="order_system_notes", indexes={@index(name="IDX_date", columns={"date"}),@index(name="IDX_note", columns={"note"})})
**/
class SystemNote{
/**
* @Id @Column(type="string")
*/
protected $id;
/**
* @var \LL_Staging\Entities\Order|null the order this item belongs to (if any)
* @ManyToOne(targetEntity="LL_Staging\Entities\Order", inversedBy="systemNotes",cascade={"persist","merge"})
* @JoinColumn(name="order_id", referencedColumnName="id")
*/
protected $order;
/**
* @Column(type="string", nullable=true)
*/
protected $user;
// ...
function __set($property, $value) {
if(is_null($this->metadata)) $this->_initialize();
$customSetter=LimeLightHelper::to_camel_case("set_".$property);
if(method_exists($this,$customSetter))
$this->$customSetter($value);
elseif(property_exists($this,$property)){
$fieldType = strtolower($this->metadata->getTypeOfField($property));
switch($fieldType){
case "datetime":
try{
$value = (is_object($value) && get_class($value)=="DateTime")?$value:new \DateTime($value);
}
catch(\Exception $e){
user_error("Invalid DateTime Value $value for $property in ".get_class($this)." Assuming NULL",E_USER_NOTICE);
$value=null;
}
$this->$property=$value;
break;
case null:
if(in_array($property,array_keys($this->relationships)))
$this->_setRelatedField($property,$value);
break;
default:
$this->$property=$value;
break;
}
}
else
user_error("Trying to write non-existing property $property in ".get_class($this),E_USER_NOTICE);
}
/**
* Saves the entity, be it an existing record or a new one. Returns the tracked entity
*
* @param Boolean (optional) if set to true, it will write this entity inmediately to the db. Defaults to FALSE
* @return
*/
function save($commit=false){
$entity =(!is_null($this->id))?$this->entityManager->find('SystemNote',$this->id):null;
if(!is_null($entity)){
$entity=$this->entityManager->merge($this);
}
else
$entity=$this;
$this->entityManager->persist($entity);
if($commit)
$this->entityManager->flush();
return $entity;
}
}
Lets suppose I already have an System Note with id 123-321 in the db.
so I do this:
$a=new SystemNote();
$a->id="123-321";
//do more stuff with the SystemNote
$a->save(true); //this will give me a mysql error that says that the key already exists, and it can not be inserted. But I do not want to INSERT, I want to UPDATE
Why does this happen and how can I fix it?
Upvotes: 0
Views: 4524
Reputation: 243
1) Avoid an unnecessary preliminary query to the database by using getReference() instead of find() to get a proxy for your entity.
$entity = $em->getReference("Entity", id);
2) Update entity properties correctly by using setters to modify the entity's protected/private fields
$entity->setStuff(...);
$entity->setMoreStuff(...);
3) Flush to the database
$em->flush();
Your existing entity should now be updated accordingly while leaving all unaltered fields intact.
Upvotes: 1
Reputation: 2769
I'm just guessing here but i think this is your problem:
$a->id="123-321";
How is this line even working when it's a protected field? I expect that your id is actually null after this line so doctrine thinks it's actually a new object.
Upvotes: 0
Reputation: 20201
First thing, in Doctrine2
, manager and data layer should be decoupled.
As for the problem, you should probably limit the persist
only to creation of new:
$this->entityManager->persist($entity);
Do not execute this line when need to update.
Upvotes: 0