Je souhaite faire une copie/clone en profondeur d'un enregistrement de doctrine dans un projet symfony. La méthode de copie existante ($ deep) ne fonctionne pas correctement avec $ deep = true.copie profonde de l'enregistrement de doctrine
Pour un exemple, jetons un coup d'œil à une leçon en classe. Cette leçon a une date de début et de fin et entre eux il y a plusieurs pauses. Cette salle de classe est dans une construction. Leçon-break est une relation un-à-plusieurs, donc beaucoup de pauses pourraient être dans une leçon. la construction de leçons est une relation plusieurs-à-un, donc une leçon ne peut être que dans un bâtiment.
Si je veux faire une copie de la pièce, les ruptures doivent également être copiées. Le bâtiment devrait rester le même (aucune copie ici).
J'ai trouvé quelques exemples sur le web qui créent une classe PHP qui s'étend à partir de sfDoctrineRecord et remplace la méthode de copie.
Ce que j'ai essayé était:
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;
}
}
Maintenant, cela provoque un échec: Doctrine_Connection_Mysql_Exception: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '2-1' for key 'PRIMARY'
donc je dois « null » l'identifiant du nouveau record ($ ret) parce que cela devrait être un nouvel enregistrement. Où et comment pourrais/devrais-je le faire?
MISE À JOUR: L'erreur est fixé avec le code suivant:
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;
}
}
Mais cela ne fonctionne pas bien. Dans la leçon DoctrineCollection-> Pauses, toutes les nouvelles pauses sont bonnes. Mais ils ne sont pas sauvegardés dans la base de données. Je veux copier une leçon et ajouter 7 jours, il est temps:
foreach($new_shift->Breaks as $break) {
$break->start_at = $this->addOneWeek($break->start_at);
$break->end_at = $this->addOneWeek($break->end_at);
$break->save();
}
Comme vous le voyez, les pauses sont sauvés, mais il semble qu'ils ne sont pas dans la db.
J'ai écrit une méthode spécifique pour mes besoins. La solution générique produit plus de problèmes qu'elle n'en résout ... Eh bien, actuellement cela ne résout aucun problème du tout :) – hering