2010-08-09 93 views
6

我想在symfony項目中對教義記錄進行深層複製/克隆。 使用$ deep = true時,現有副本($ deep) - 方法無法正常工作。教條記錄的深層副本

舉個例子,讓我們看看課堂課。這節課有一個開始和結束的日期,在它們之間有幾個休息時間。這間教室正在建造中。

課堂休息是一種一對多的關係,所以課堂上可能會有很多休息時間。 建構教學是多對一的關係,所以一堂課只能在一棟建築物中進行。

如果我想製作房間的副本,應該複製這些休息。建築應該保持不變(這裏不要複製)。

我在網上找到了一些創建PHP類的例子,它從sfDoctrineRecord擴展並覆蓋了copy-method。

我想什麼:

class BaseDoctrineRecord extends sfDoctrineRecord { 
    public function copy($deep = false) { 
     $ret = parent::copy(false); 
     if (!$deep) 
      return $ret; 

     // ensure to have loaded all references (unlike Doctrine_Record) 
     foreach ($this->getTable()->getRelations() as $name => $relation) { 
      // ignore ONE sides of relationships 
      if ($relation->getType() == Doctrine_Relation::MANY) { 
       if (empty($this->$name)) 
        $this->loadReference($name); 

       // do the deep copy 
       foreach ($this->$name as $record) 
        $ret->{$name}[] = $record->copy($deep); 
      } 
     } 
     return $ret; 
    } 
} 

現在,這導致了失敗:Doctrine_Connection_Mysql_Exception: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '2-1' for key 'PRIMARY'

所以我需要爲「空」的新紀錄($ RET)的ID,因爲這應該是一個新紀錄。我應該在哪裏以及如何做到這一點?

UPDATE: 錯誤是固定的下面的代碼:

class BaseDoctrineRecord extends sfDoctrineRecord { 
    public function copy($deep = false) { 
     $ret = parent::copy(false); 

     if($this->Table->getIdentifierType() === Doctrine_Core::IDENTIFIER_AUTOINC) { 
      $id = $this->Table->getIdentifier(); 
      $this->_data[$id] = null; 
     } 

     if(!$deep) { 
      return $ret; 
     } 

     // ensure to have loaded all references (unlike Doctrine_Record) 
     foreach($this->getTable()->getRelations() as $name => $relation) { 
      // ignore ONE sides of relationships 
      if($relation->getType() == Doctrine_Relation::MANY) { 
       if(empty($this->$name)) { 
        $this->loadReference($name); 
       } 

       // do the deep copy 
       foreach($this->$name as $record) { 
        $ret->{$name}[] = $record->copy($deep); 
       } 
      } 
     } 

     return $ret; 
    } 
} 

但它不能很好地工作。在DoctrineCollection課程 - >打破所有新的休息都沒問題。但它們不會保存在數據庫中。 我要複製一個教訓,增加7天,它的時間:

foreach($new_shift->Breaks as $break) { 
    $break->start_at = $this->addOneWeek($break->start_at); 
    $break->end_at = $this->addOneWeek($break->end_at); 
    $break->save(); 
} 

所以你看,休息時間都省了,但似乎他們不是在分貝。

+0

我已經爲我的需求編寫了特定的方法。通用的解決方案會產生比解決問題更多的問題......好吧,目前它根本沒有解決任何問題:) – hering 2010-08-11 09:28:16

回答

0

托馬斯坦克引擎正在我耳邊爆炸,所以我不能專注於你的問題的更精細的點,但它聽起來很熟悉。這回答了你的問題了嗎?

Copy a Doctrine object with all relations

基本上Doctrine_Record::link()方法是你的朋友:)

+1

其實......我的確讀過你的問題。我給出的答案是當你想複製一份記錄,但保留原始參考文獻,即:*不復制相關記錄。 我敢打賭,你正在使用Doctrine 1.0。在Doctrine 1.2中解決了複製(深層)問題(以及許多其他有用的東西,例如synchronizeWithArray())。當您在Doctrine 1.2中進行深度複製時,它將複製並保存參考也沒有問題。 我不知道是否升級到1.2是一個選項,雖然... – 2010-08-09 19:00:19

+1

其實我有版本1.4.4 :) – hering 2010-08-10 13:28:19

+0

哈哈。噢,沒關係:D – 2010-08-10 20:43:38

0

這個工作對我來說,這是一個從問題的代碼變體:

public function realCopy($deep = false) { 
    $ret = self::copy(false); 

    if(!$deep) { 
     return $ret; 
    } 

    // ensure to have loaded all references (unlike Doctrine_Record) 
    foreach($this->getTable()->getRelations() as $name => $relation) { 
     // ignore ONE sides of relationships 
     if($relation->getType() == Doctrine_Relation::MANY) { 
      if(empty($this->$name)) { 
       $this->loadReference($name); 
      } 

      // do the deep copy 
      foreach($this->$name as $record) { 
       $ret->{$name}[] = $record->realCopy($deep); 
      } 
     } 
    } 

    // this need to be at the end to ensure Doctrine is able to load the relations data 
    if($this->Table->getIdentifierType() === Doctrine_Core::IDENTIFIER_AUTOINC) { 
     $id = $this->Table->getIdentifier(); 
     $this->_data[$id] = null; 
    } 

    return $ret; 
} 

我不能相信我在2017年與Doctrine 1.2一起工作。