2010-08-09 17 views
6

Quiero hacer una copia/copia profunda de un registro de doctrina en un proyecto de Symfony. El método de copia existente ($ profundo) no funciona correctamente con $ profundo = verdadero.copia en profundidad del registro de la doctrina

Por ejemplo, echemos un vistazo a una clase de clase. Esta lección tiene una fecha de inicio y finalización y entre ellos hay varios descansos. Este aula está en un buildung.

salto de clase es una relación de uno a varios, por lo que una gran cantidad de descansos pueden ser dentro de una lección. la construcción de lecciones es una relación de varios a uno, por lo que una lección solo podría ser en UN EDIFICIO.

Si quiero hacer una copia de la sala, también se deben copiar los descansos. El edificio debe permanecer igual (no copia aquí).

Encontré algunos ejemplos en la web que crean una clase de PHP que se extiende desde sfDoctrineRecord y anula el método de copia.

Lo que intenté fue:

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

Ahora bien, esto hace que en un fracaso: Doctrine_Connection_Mysql_Exception: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '2-1' for key 'PRIMARY'

por lo que necesito "nulo" el ID del nuevo registro ($ ret), ya que esto debe ser una nuevo record. ¿Dónde y cómo podría/debería hacerlo?

ACTUALIZACIÓN: El error se fija con el código siguiente:

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

Pero no funciona bien. En la lección de DoctrineCollection-> Rompe todos los descansos nuevos están bien. Pero no se guardan en la base de datos. quiero copiar una lección y añadir 7 días a la misma hora:

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

Así que como ves, los descansos son salvados, pero parece que no están en el PP.

+0

He escrito un método específico para mis necesidades. La solución genérica produce más problemas de los que resuelve ... Bueno, actualmente no resuelve ningún problema :) – hering

Respuesta

0

Thomas the Tank Engine está volando en mi oído en este momento, así que no puedo concentrarme en los puntos más finos de su pregunta, pero me suena familiar. ¿Responde esto a tu pregunta?

Copy a Doctrine object with all relations

Básicamente el método Doctrine_Record::link() es su amigo :)

+1

en realidad ... Leí su pregunta incorrectamente. la respuesta que di se refiere a cuándo desea copiar un registro, pero conserva las referencias originales, es decir: * no * copia los registros relacionados. Estoy dispuesto a apostar que estás usando Doctrine 1.0. El problema de la copia (profunda) se resuelve (junto con muchas otras cosas útiles como synchronizeWithArray()) en Doctrine 1.2. Cuando copie profundamente en Doctrine 1.2, copiará y guardará las referencias, sin problema. No sé si actualizar a 1.2 es una opción para usted ... –

+1

En realidad tengo la versión 1.4.4 :) – hering

+0

jaja. oh, cierto ... no importa: D –

0

Esto funciona para mí, es una variante del código de pregunta:

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

No puedo creer que esté trabajando con Doctrine 1.2 en 2017.

Cuestiones relacionadas