Доктрина множественное однонаправленное/однонаправленное нарушение ограничения целостности
В последней доктрине о Symfony2 пытается выработать множественную двунаправленную связь между двумя объектами.
Объект владельца человека имеет один почтовый адрес, а затем несколько дополнительных адресов в коллекции, и я удаляю() Человека, я хочу, чтобы все его адреса также были удалены (но удаление адреса не должно удалять человека), но я получаю эту ошибку -
An exception occurred while executing 'DELETE FROM address WHERE id = ?' with
params {"1":"fb5e47de-2651-4069-b85e-8dbcbe8a6c4a"}:
[PDOException] SQLSTATE[23000]: Integrity constraint violation: 1451
Cannot delete or update a parent row: a foreign key constraint fails
(`db`.`address`, CONSTRAINT `FK_633704 C29C1004E`
FOREIGN KEY (`person_id`) REFERENCES `person` (`id`))
В
class Person
{
/**
* @var Address postalAddress
*
* @ORM\OneToOne(targetEntity="Address", cascade={"all"}, orphanRemoval=true)
* @ORM\JoinColumn(onDelete="cascade")
*/
private $postalAddress;
/**
* @var \Doctrine\Common\Collections\Collection otherAddresses
*
* @ORM\OneToMany(targetEntity="Address", mappedBy="person", cascade={"all"}, orphanRemoval=true)
*/
private $otherAddresses;
}
class Address
{
/**
* @var Person person
*
* @ORM\ManyToOne(targetEntity="Person", inversedBy="postalAddress, otherAddresses")
* @ORM\JoinColumn(nullable=false)
*/
private $person;
}
Я подумал, что это может быть, потому что
inversedBy="postalAddress, otherAddresses"
Я не думаю, что поддерживается множественное инвертирование; затем я также попытался изменить
@ORM\JoinColumn(nullable=false)
Быть обнуляемым, но я все равно получаю ошибку.
Очевидно, что речь идет не о тривиальном примере человека/адреса, а о чем-то более сложном, но это была моя лучшая попытка абстракции.
Я уверен, что упустил что-то очевидное. Кто-нибудь может помочь?
1 answers
Нарушенное определение отношений
Хотя то, что вы делаете, может иметь смысл с чисто логической точки зрения, это не имеет смысла с точки зрения реляционных данных и, в частности, не имеет смысла с точки зрения Доктрины.
Доктрина пытается поддерживать 3 различных отношения:
-
Адрес (сторона владельца) [двунаправленный] $человек
--Many:One-->
$Другие адреса Человек -
Адрес (сторона владельца) [двунаправленный] $персона
--Many:One-->
$Почтовый адрес Персона -
Лицо (сторона владельца) [однонаправленный] $Почтовый адрес
--One:One-->
$идентификатор Адрес
Вы видите проблему?
Используйте реляционные стандарты для решения этой проблемы.
Простое решение здесь состоит в том, чтобы использовать ОЧЕНЬ распространенный шаблон проектирования установки первичного элемента для коллекции. По сути, вам нужна только одна связь:
-
Адрес (сторона владельца) [двунаправленный] $персона
--Many:One-->
$Другие адреса Персона
Затем добавьте в адрес свойство, которое определяет этот адрес как основной. Программно обработайте это в лицах и адресных сущностях:
Class Person
{
. . .
public function getPrimaryAddress() {
if (null === $this->primaryAddress) {
foreach($this->getOtherAddresses() as $address) {
if ($address->isPrimary()) {
$this->primaryAddress = $address;
break;
}
}
}
return $this->primaryAddress;
}
// similar for the setter, update the old address as not primary if there is one, set the new one as primary.
}
Используйте два разных отношения, но не пересекайте потоки
Если вы сохраняете ОДНОНАПРАВЛЕННЫЕ отношения "Один к одному" от человека к адресату, проблема решается сама собой.
-
Адрес (сторона владельца) [двунаправленный] $человек
--Many:One-->
$Другие адреса Человек -
Лицо (сторона владельца) [однонаправленный] $Почтовый адрес
--One:One-->
Адрес
Однако здесь у вас все равно будут проблемы, потому что Доктрина будет жаловаться, если:
- основной (Почтовый адрес ) адрес не имеет обеих сторон для Многих:Один определен. (таким образом, ваш "основной" адрес также должен быть в коллекции $otherAddresses
).
- попытка удалить или каскадировать удаление и обновление приведут к конфликту этих двух отношений, "пересечению потоков" реляционных ограничений доктрины, поэтому вам придется программно обрабатывать эти операции.