2010-08-09 18 views
6

मैं एक सिम्फनी परियोजना में एक सिद्धांत रिकॉर्ड की गहरी प्रतिलिपि/क्लोन बनाना चाहता हूं। मौजूदा प्रतिलिपि ($ गहरी) - विधि $ deep = true के साथ ठीक से काम नहीं करती है।सिद्धांत रिकॉर्ड की गहरी प्रति

उदाहरण के लिए चलो कक्षा के पाठ को देखें। इस पाठ में एक प्रारंभ और समाप्ति तिथि है और उनके बीच कई ब्रेक हैं। यह कक्षा एक बिल्डिंग में है।

सबक-ब्रेक एक से कई रिश्ते हैं, इसलिए एक सबक के अंदर बहुत सारे ब्रेक हो सकते हैं। सबक-बिल्डिंग एक से एक रिश्ते है, इसलिए एक सबक केवल एक बिल्डिंग में ही हो सकता है।

यदि मैं कमरे की एक प्रति बनाना चाहता हूं तो ब्रेक की प्रतिलिपि बनाई जानी चाहिए। इमारत को वही रहना चाहिए (यहां कोई प्रतिलिपि नहीं है)।

मुझे वेब पर कुछ उदाहरण मिले जो एक PHP वर्ग बनाते हैं जो sfDoctrineRecord से फैली हुई है और कॉपी-विधि को ओवरराइड करता है।

मैं क्या करने की कोशिश की थी:

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'

तो मैं "अशक्त" नया रिकार्ड ($ सेवानिवृत्त) की आईडी क्योंकि यह एक होना चाहिए की जरूरत है नया रिकॉर्ड। मैं कहां और कैसे कर सकता/सकती हूं?

अद्यतन: त्रुटि निम्न कोड के साथ तय हो गई है:

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

लेकिन यह अच्छी तरह से काम नहीं करता। सिद्धांत में चयन पाठ-> सभी नए ब्रेक तोड़ते हैं ठीक है। लेकिन वे डेटाबेस में सहेजे नहीं गए हैं। मैं एक सबक कॉपी और 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(); 
} 

तो जैसा कि आप देख, टूटता सहेजे जाते हैं, लेकिन ऐसा लगता है कि वे DB में नहीं हैं।

+0

मैंने अपनी ज़रूरतों के लिए एक विशिष्ट विधि लिखी है। जेनेरिक समाधान हल होने की तुलना में अधिक समस्याएं उत्पन्न करता है ... अच्छा, वर्तमान में यह किसी भी समस्या का समाधान नहीं करता है :) – hering

उत्तर

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

मैं विश्वास नहीं कर सकता मैं कर रहा हूँ:

Copy a Doctrine object with all relations

मूल रूप से Doctrine_Record::link() विधि अपने दोस्त :)

+1

वास्तव में ... मैंने आपका प्रश्न गलत पढ़ा है। मैंने जो जवाब दिया है वह उस समय के लिए है जब आप एक रिकॉर्ड कॉपी करना चाहते हैं, लेकिन मूल संदर्भ बनाए रखें, i.e: * नहीं * संबंधित रिकॉर्ड कॉपी करें। मैं शर्त लगाता हूं कि आप सिद्धांत 1.0 का उपयोग कर रहे हैं। कॉपी (गहरी) समस्या को हल किया गया है (साथ ही कई अन्य उपयोगी सामग्री जैसे सिंक्रनाइज़ WithArray()) सिद्धांत 1.2 में। जब आप सिद्धांत 1.2 में गहरी प्रतिलिपि करते हैं तो यह संदर्भों की प्रतिलिपि और सहेजने में भी कोई समस्या नहीं होगी। मुझे नहीं पता कि 1.2 के लिए अपग्रेड करना आपके लिए एक विकल्प है हालांकि ... –

+1

असल में मुझे संस्करण 1.4.4 मिला :) – hering

+0

हाहा। ओह ठीक है ... कभी नहीं सोचा: डी –

0

यह मेरे लिए काम करता है, यह सवाल कोड से एक प्रकार है 2017 में सिद्धांत 1.2 के साथ काम करना।

संबंधित मुद्दे