dorphalsig
dorphalsig

Reputation: 711

Doctrine 2.0- Will not update entity

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

Answers (3)

Eric Amshukov
Eric Amshukov

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

Derick F
Derick F

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

Jovan Perovic
Jovan Perovic

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

Related Questions