Я хочу сделать глубокую копию / клон записи доктрины в проекте 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]: Нарушение ограничения целостности: 1062 Повторяющаяся запись '2-1' для ключа 'PRIMARY'
Так что мне нужно «обнулить» идентификатор новой записи ($ ret), потому что это должна быть новая запись. Где и как я могу / должен это сделать?
ОБНОВЛЕНИЕ: Ошибка исправлена с помощью следующего кода:
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();
}
Итак, как вы видите, разрывы сохраняются, но, похоже, их нет в БД.