2010-08-09 38 views
6

Tôi muốn tạo bản sao sâu/bản sao của một bản ghi học thuyết trong một dự án symfony. Phương thức sao chép ($ sâu) hiện tại không hoạt động đúng với $ deep = true.bản sao sâu của hồ sơ giáo lý

Ví dụ, chúng ta hãy xem bài học trên lớp học. Bài học này có ngày bắt đầu và ngày kết thúc và giữa chúng có một số lần ngắt. Lớp học này đang được xây dựng.

bài học-break là mối quan hệ một-nhiều, vì vậy rất nhiều giờ nghỉ có thể nằm trong một bài học. xây dựng bài học là mối quan hệ nhiều người, do đó, một bài học chỉ có thể ở trong ONE Building.

Nếu tôi muốn sao chép căn phòng, các điểm ngắt cũng phải được sao chép. Tòa nhà nên giữ nguyên (không có bản sao ở đây).

Tôi đã tìm thấy một số ví dụ trên web tạo lớp PHP mở rộng từ sfDoctrineRecord và ghi đè phương thức sao chép.

Những gì tôi cố gắng là:

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

Bây giờ điều này gây ra trong một thất bại: Doctrine_Connection_Mysql_Exception: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '2-1' for key 'PRIMARY'

Vì vậy, tôi cần phải "null" id của bản ghi mới ($ ret) vì đây phải là một kỷ lục mới. Tôi nên làm ở đâu và như thế nào?

UPDATE: Các lỗi được cố định với đoạn mã sau:

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

Nhưng nó không hoạt động tốt. Trong bài học DoctrineCollection-> Breaks tất cả các ngắt mới đều ổn. Nhưng chúng không được lưu trong cơ sở dữ liệu. Tôi muốn sao chép một bài học và thêm 7 ngày để đó là thời gian:

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

Vì vậy, như bạn thấy, các vi phạm được lưu, nhưng có vẻ như họ không nằm trong db.

+0

Tôi đã viết một phương pháp cụ thể cho các nhu cầu của mình. Các giải pháp chung sản xuất nhiều vấn đề hơn là nó giải quyết ... Vâng, hiện tại nó không giải quyết bất kỳ vấn đề ở tất cả :) – hering

Trả lời

0

Thomas Tank Engine đang nổ mìn trong tai của tôi vào lúc này vì vậy tôi không thể tập trung vào những điểm tốt hơn trong câu hỏi của bạn, nhưng nghe có vẻ quen thuộc. Điều này có trả lời câu hỏi của bạn không?

Copy a Doctrine object with all relations

Về cơ bản các phương pháp Doctrine_Record::link() là bạn của bạn :)

+1

thực sự ... Tôi đã đọc câu hỏi của bạn sai. câu trả lời tôi đưa ra là khi bạn muốn sao chép một bản ghi, nhưng giữ nguyên các tham chiếu ban đầu, tức là: * không * sao chép các bản ghi liên quan. Tôi sẵn sàng đặt cược bạn đang sử dụng Doctrine 1.0. Vấn đề sao chép (sâu) được giải quyết (cùng với nhiều công cụ hữu ích khác như synchronizeWithArray()) trong Doctrine 1.2. Khi bạn sao chép sâu trong Doctrine 1.2 nó sẽ sao chép và lưu các tài liệu tham khảo cũng không có vấn đề. Tôi không biết liệu nâng cấp lên 1.2 có phải là tùy chọn cho bạn hay không ... –

+1

Thực ra tôi có phiên bản 1.4.4 :) – hering

+0

haha. ồ phải ... đừng bận tâm: D –

0

này làm việc cho tôi, đó là một biến thể từ mã câu hỏi:

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

Tôi không thể tin rằng tôi làm việc với Doctrine 1.2 trong năm 2017.