Я хочу сделать глубокую копию / клон записи доктрины в проекте Symfony.
Существующий метод копирования ($ deep) не работает должным образом с $ deep = true.
Для примера давайте посмотрим на урок в классе. У этого урока есть дата начала и окончания, и между ними есть несколько перерывов. Этот класс находится в здании.
перерыв в уроке - это отношение один ко многим, поэтому в уроке может быть много перерывов.
построение урока - это отношения многих к одному, поэтому урок может быть только в ОДНОМ здании.
Если я хочу сделать копию комнаты, перерывы также должны быть скопированы. Здание должно остаться прежним (здесь нет копии).
Я нашел несколько примеров в Интернете, которые создают класс PHP, который выходит из sfDoctrineRecord и переопределяет метод копирования.
То, что я пробовал, было:
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;
}
}
Теперь это приводит к ошибке: Doctrine_Connection_Mysql_Exception: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '2-1' for key 'PRIMARY'
Так что мне нужно «обнулить» идентификатор новой записи ($ ret), потому что это должна быть новая запись. Где и как я мог / должен это сделать?
UPDATE:
Ошибка исправлена с помощью следующего кода:
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;
}
}
Но это не работает хорошо. В уроке DoctrineCollection-> Перерывы все новые перерывы в порядке. Но они не сохраняются в базе данных.
Я хочу скопировать урок и добавить к нему 7 дней:
foreach($new_shift->Breaks as $break) {
$break->start_at = $this->addOneWeek($break->start_at);
$break->end_at = $this->addOneWeek($break->end_at);
$break->save();
}
Итак, как вы видите, разрывы сохраняются, но, похоже, их нет в БД.