title: deep copy of doctrine record
body: <p>I want to make a deep copy/clone of a doctrine record in a symfony project.
  The existing copy($deep)-method doesn't work properly with $deep=true.</p>
  
  <p>For an example let's have a look at a classroom lesson. This lesson has a start and end date and between them there are several breaks. This classroom is in a buildung.</p>
  
  <p>lesson-break is a one-to-many relationship, so a lot of breaks could be inside a lesson.
  lesson-building is a many-to-one relationship, so a lesson could only be in ONE Building.</p>
  
  <p>If I want to make a copy of the room the breaks should be copied also. The building should stay the same (no copy here).</p>
  
  <p>I found some examples on the web which create a PHP class which extends from the sfDoctrineRecord and overrides the copy-method.</p>
  
  <p>What I tried was:</p>
  
  <pre><code>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-&gt;getTable()-&gt;getRelations() as $name =&gt; $relation) {
              // ignore ONE sides of relationships
              if ($relation-&gt;getType() == Doctrine_Relation::MANY) {
                  if (empty($this-&gt;$name))
                      $this-&gt;loadReference($name);
  
                  // do the deep copy
                  foreach ($this-&gt;$name as $record)
                      $ret-&gt;{$name}[] = $record-&gt;copy($deep);
              }
          }
          return $ret;
      }
  }
  </code></pre>
  
  <p>Now this causes in a failure: <code>Doctrine_Connection_Mysql_Exception: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '2-1' for key 'PRIMARY'</code></p>
  
  <p>So I need to "null" the id of the new record ($ret) because this should be a new record. Where and how could/should I do it?</p>
  
  <p>UPDATE:
  The error is fixed with following code:</p>
  
  <pre><code>class BaseDoctrineRecord extends sfDoctrineRecord {
      public function copy($deep = false)  {
          $ret = parent::copy(false);
  
          if($this-&gt;Table-&gt;getIdentifierType() === Doctrine_Core::IDENTIFIER_AUTOINC) {
              $id = $this-&gt;Table-&gt;getIdentifier();
              $this-&gt;_data[$id] = null;
          }
  
          if(!$deep) {
              return $ret;
          }
  
          // ensure to have loaded all references (unlike Doctrine_Record)
          foreach($this-&gt;getTable()-&gt;getRelations() as $name =&gt; $relation) {
              // ignore ONE sides of relationships
              if($relation-&gt;getType() == Doctrine_Relation::MANY) {
                  if(empty($this-&gt;$name)) {
                      $this-&gt;loadReference($name);
                  }
  
                  // do the deep copy
                  foreach($this-&gt;$name as $record) {
                      $ret-&gt;{$name}[] = $record-&gt;copy($deep);
                  }
              }
          }
  
          return $ret;
      }
  }
  </code></pre>
  
  <p>But it doesn't work well. In the DoctrineCollection lesson->Breaks all new breaks are fine. But they aren't saved in the database.
  I want to copy a lesson and add 7 days to it's time:</p>
  
  <pre><code>foreach($new_shift-&gt;Breaks as $break) {
      $break-&gt;start_at = $this-&gt;addOneWeek($break-&gt;start_at);
      $break-&gt;end_at = $this-&gt;addOneWeek($break-&gt;end_at);
      $break-&gt;save();
  }
  </code></pre>
  
  <p>So as you see, the breaks are saved, but it seems they are not in the db.</p>