Ich möchte eine tiefe Kopie/Klon eines Doktrin Datensatzes in einem symfony Projekt machen. Die vorhandene Kopie ($ deep) -Methode funktioniert nicht ordnungsgemäß mit $ deep = true.tiefe Kopie der Doktrin
Für ein Beispiel schauen wir uns eine Unterrichtseinheit an. Diese Lektion hat ein Start- und Enddatum und dazwischen gibt es mehrere Pausen. Dieses Klassenzimmer befindet sich in einem Gebäude.
Lektionen brechen ist eine Eins-zu-viele-Beziehung, so dass viele Pausen in einer Lektion sein können. Das Lernen von Unterricht ist eine Beziehung, in der viele miteinander in Beziehung stehen, so dass eine Lektion nur in EINEM Gebäude stattfinden kann.
Wenn ich eine Kopie des Zimmers machen möchte, sollten die Pausen auch kopiert werden. Das Gebäude sollte gleich bleiben (keine Kopie hier).
Ich habe einige Beispiele im Web gefunden, die eine PHP-Klasse erstellen, die sich von sfDoctrineRecord erstreckt und die Kopiermethode überschreibt.
Was ich versucht war:
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;
}
}
Jetzt führt dies zu einem Fehler: Doctrine_Connection_Mysql_Exception: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '2-1' for key 'PRIMARY'
Also habe ich die ID des neuen Datensatzes ($ ret) auf "null" müssen, weil dies eine sein sollte, Neuer Eintrag. Wo und wie könnte/sollte ich es tun?
UPDATE: Der Fehler mit folgendem Code festgelegt ist:
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;
}
}
Aber es funktioniert nicht gut. In der DoctrineCollection-Lektion-> Pausen sind alle neuen Pausen in Ordnung. Sie werden jedoch nicht in der Datenbank gespeichert. Ich mag eine Lektion kopieren und 7 Tage in dem es an der Zeit:
foreach($new_shift->Breaks as $break) {
$break->start_at = $this->addOneWeek($break->start_at);
$break->end_at = $this->addOneWeek($break->end_at);
$break->save();
}
So wie Sie sehen, sind die Pausen gespeichert, aber es scheint, dass sie nicht in der db sind.
Ich habe eine spezielle Methode für meine Bedürfnisse geschrieben. Die generische Lösung erzeugt mehr Probleme als sie löst ... Nun, im Moment löst sie überhaupt kein Problem :) – hering