2014-09-05 2 views
0

Я создаю первичный ключ (строка) для объекта, и я пытаюсь его обновить. Однако, когда я вызываю $ em-> persist(), а затем $ em-> flush() Doctrine пытается INSERT создать новую запись вместо обновления существующей.Doctrine 2.0- Не будет обновлять объект

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; 
} 


} 

Давайте предположим, у меня уже есть системы с идентификатором Примечание 123-321 в БД.

, так что я это сделать:

$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 

Почему это происходит и как я могу это исправить?

ответ

0

Прежде всего, в Doctrine2, менеджер и слой данных должны быть разделены.

Что касается проблемы, вы, вероятно, следует ограничить persist только к созданию нового:

$this->entityManager->persist($entity); 

Не выполнять эту строку, когда нужно обновить.

+0

Не будет ничего ужасного, если упорствовать в случае обновления. Но, конечно, можно сохранить существующую сущность без сохранения. – sergekv

+0

$ this-> entityManager-> Merge() - это способ сделать это? –

0

Я просто предполагаю здесь, но я думаю, что это ваша проблема:

$a->id="123-321"; 

Как эта линия даже работает, когда это защищенное поле? Я ожидаю, что ваш id на самом деле является нулевым после этой строки, поэтому доктрина считает, что это фактически новый объект.

+0

Попытка установить защищенное свойство, таким образом, приведет к фатальной ошибке, не так ли? http://php.net/manual/en/language.oop5.visibility.php – sergekv

+0

Да, извините, мне не удалось скопировать общий набор, который это делает. Код обновлен. :) Проблема сохраняется. –

1

1) Избегайте ненужного предварительного запроса к базе данных с помощью getReference() вместо find(), чтобы получить прокси для вашего объекта.

$entity = $em->getReference("Entity", id); 

2) Обновление свойства сущностей правильно с помощью сеттеры изменить защищенные/частные поля аудируемого лица

$entity->setStuff(...); 
$entity->setMoreStuff(...); 

3) Flush к базе данных

$em->flush(); 

Ваш существующий объект должен теперь обновляйтесь соответствующим образом, оставляя неизмененные поля неизменными.

Смежные вопросы