删除用户时虚拟多对多用户关系中的外键问题
Foreign Key issue in a virtual many-to-many user relationship when removing user
在我的 Symfony 应用程序中,我必须处理某种友谊请求。它基本上是用户之间的多对多关系,但是有一个 accepted
布尔值 属性 和一个 createdAt
DateTime,因此我创建了一个独立的“友谊”实体而不是一个多对多用户实体中的许多关系。
问题是:我有一个 Sender
属性(与用户的一对多关系)和一个 recipient
属性(与用户的一对多关系)用户也是如此)。我在用户 属性 中将 orphanRemoval
设置为 true。
但是,如果我删除一个只有朋友的用户,而他是发件人,它会很好地删除朋友实体。但是如果他是好友请求的接收者,它就不起作用并且 returns 一个外键约束错误,更准确地说
SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or
update a parent row: a foreign key constraint fails
(portail
.friendship
, CONSTRAINT FK_7234A45FE92F8F78
FOREIGN KEY (recipient_id
) REFERENCES user
(id
)).
我估计这与用户在我的友谊实体中出现两次有关,显然,addFriendship()
/ removeFriendship()
方法中似乎只提到了发件人,但我不确定如何解决它,我想知道我是否没有以正确的方式解决这个问题,以及我可以做些什么来改变它并让它发挥作用(即:删除所有与友谊相关的给用户,无论他是发件人还是收件人)。
下面是friendship实体,以及User实体中提到Friendship实体关系的部分。
<?php
namespace App\Entity;
use App\Repository\FriendshipRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=FriendshipRepository::class)
*/
class Friendship
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity=User::class, inversedBy="friendships")
* @ORM\JoinColumn(nullable=false)
*/
private ?User $sender;
/**
* @ORM\ManyToOne(targetEntity=User::class, inversedBy="friendships")
* @ORM\JoinColumn(nullable=false)
*/
private ?User $recipient;
/**
* @ORM\Column(type="boolean")
*/
private ?bool $accepted;
/**
* @ORM\Column(type="datetime_immutable")
*/
private ?\DateTimeImmutable $createdAt;
public function getId(): ?int
{
return $this->id;
}
public function getSender(): ?User
{
return $this->sender;
}
public function setSender(?User $sender): self
{
$this->sender = $sender;
return $this;
}
public function getRecipient(): ?User
{
return $this->recipient;
}
public function setRecipient(?User $recipient): self
{
$this->recipient = $recipient;
return $this;
}
public function getAccepted(): ?bool
{
return $this->accepted;
}
public function setAccepted(bool $accepted): self
{
$this->accepted = $accepted;
return $this;
}
public function getCreatedAt(): ?\DateTimeImmutable
{
return $this->createdAt;
}
public function setCreatedAt(\DateTimeImmutable $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
}
部分用户
/**
* @ORM\OneToMany(targetEntity=Friendship::class, mappedBy="sender", orphanRemoval=true)
*/
private $friendships;
/**
* @return Collection|Friendship[]
*/
public function getFriendships(): Collection
{
return $this->friendships;
}
public function addFriendship(Friendship $friendship): self
{
if (!$this->friendships->contains($friendship)) {
$this->friendships[] = $friendship;
$friendship->setSender($this);
}
return $this;
}
public function removeFriendship(Friendship $friendship): self
{
if ($this->friendships->removeElement($friendship)) {
// set the owning side to null (unless already changed)
if ($friendship->getSender() === $this) {
$friendship->setSender(null);
}
}
return $this;
}
Arleigh 确实是正确的。我做错的是设置了相同的名称,即 Friendships
,同时更新我的 friendship
实体以获得用户中的两个关系,无论他是 sender
还是 recipient
。我认为这会让我更容易地在我的控制器和 twig 模板中获得与用户相关的所有 friendships
,无论它们是 recipient
还是 sender
但最后,所有它确实让一切都出错了。
我通过在我的用户中有两个单独的属性来修复它,friendshipRequestsSent
(由 Friendship
实体的 sender
字段映射)和 friendshipRequestsReceived
(映射通过 Friendship
实体的 recpient
字段)以及相关属性的方法和类型。这就是我现在 User
实体中的样子
/**
* @ORM\OneToMany(targetEntity=Friendship::class, mappedBy="sender", orphanRemoval=true)
*/
private $friendshipRequestsSent;
/**
* @ORM\OneToMany(targetEntity=Friendship::class, mappedBy="recipient", orphanRemoval=true)
*/
private $friendshipRequestsReceived;
public function __construct()
{
$this->userSkills = new ArrayCollection();
$this->experiences = new ArrayCollection();
$this->missions = new ArrayCollection();
$this->friendshipRequestsSent = new ArrayCollection();
$this->friendshipRequestsReceived = new ArrayCollection();
}
/**
* @return Collection|Friendship[]
*/
public function getFriendshipRequestsSent(): Collection
{
return $this->friendshipRequestsSent;
}
public function addFriendshipRequestSent(Friendship $friendship): self
{
if (!$this->friendshipRequestsSent->contains($friendship)) {
$this->friendshipRequestsSent[] = $friendship;
$friendship->setSender($this);
}
return $this;
}
public function removeFriendshipRequestSent(Friendship $friendship): self
{
if ($this->friendshipRequestsSent->removeElement($friendship)) {
// set the owning side to null (unless already changed)
if ($friendship->getSender() === $this) {
$friendship->setSender(null);
}
}
return $this;
}
/**
* @return Collection|Friendship[]
*/
public function getFriendshipRequestsReceived(): Collection
{
return $this->friendshipRequestsReceived;
}
public function addFriendshipRequestReceived(Friendship $friendship): self
{
if (!$this->friendshipRequestsReceived->contains($friendship)) {
$this->friendshipRequestsReceived[] = $friendship;
$friendship->setSender($this);
}
return $this;
}
public function removeFriendshipRequestReceived(Friendship $friendship): self
{
if ($this->friendshipRequestsReceived->removeElement($friendship)) {
// set the owning side to null (unless already changed)
if ($friendship->getSender() === $this) {
$friendship->setSender(null);
}
}
return $this;
}
这就是我的 Friendship
实体 sender
和 recipient
属性的声明方式
/**
* @ORM\ManyToOne(targetEntity=User::class, inversedBy="friendshipRequestsSent")
* @ORM\JoinColumn(nullable=false)
*/
private ?User $sender;
/**
* @ORM\ManyToOne(targetEntity=User::class, inversedBy="friendshipRequestsReceived")
* @ORM\JoinColumn(nullable=false)
*/
private ?User $recipient;
在我的 Symfony 应用程序中,我必须处理某种友谊请求。它基本上是用户之间的多对多关系,但是有一个 accepted
布尔值 属性 和一个 createdAt
DateTime,因此我创建了一个独立的“友谊”实体而不是一个多对多用户实体中的许多关系。
问题是:我有一个 Sender
属性(与用户的一对多关系)和一个 recipient
属性(与用户的一对多关系)用户也是如此)。我在用户 属性 中将 orphanRemoval
设置为 true。
但是,如果我删除一个只有朋友的用户,而他是发件人,它会很好地删除朋友实体。但是如果他是好友请求的接收者,它就不起作用并且 returns 一个外键约束错误,更准确地说
SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails (
portail
.friendship
, CONSTRAINTFK_7234A45FE92F8F78
FOREIGN KEY (recipient_id
) REFERENCESuser
(id
)).
我估计这与用户在我的友谊实体中出现两次有关,显然,addFriendship()
/ removeFriendship()
方法中似乎只提到了发件人,但我不确定如何解决它,我想知道我是否没有以正确的方式解决这个问题,以及我可以做些什么来改变它并让它发挥作用(即:删除所有与友谊相关的给用户,无论他是发件人还是收件人)。
下面是friendship实体,以及User实体中提到Friendship实体关系的部分。
<?php
namespace App\Entity;
use App\Repository\FriendshipRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=FriendshipRepository::class)
*/
class Friendship
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity=User::class, inversedBy="friendships")
* @ORM\JoinColumn(nullable=false)
*/
private ?User $sender;
/**
* @ORM\ManyToOne(targetEntity=User::class, inversedBy="friendships")
* @ORM\JoinColumn(nullable=false)
*/
private ?User $recipient;
/**
* @ORM\Column(type="boolean")
*/
private ?bool $accepted;
/**
* @ORM\Column(type="datetime_immutable")
*/
private ?\DateTimeImmutable $createdAt;
public function getId(): ?int
{
return $this->id;
}
public function getSender(): ?User
{
return $this->sender;
}
public function setSender(?User $sender): self
{
$this->sender = $sender;
return $this;
}
public function getRecipient(): ?User
{
return $this->recipient;
}
public function setRecipient(?User $recipient): self
{
$this->recipient = $recipient;
return $this;
}
public function getAccepted(): ?bool
{
return $this->accepted;
}
public function setAccepted(bool $accepted): self
{
$this->accepted = $accepted;
return $this;
}
public function getCreatedAt(): ?\DateTimeImmutable
{
return $this->createdAt;
}
public function setCreatedAt(\DateTimeImmutable $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
}
部分用户
/**
* @ORM\OneToMany(targetEntity=Friendship::class, mappedBy="sender", orphanRemoval=true)
*/
private $friendships;
/**
* @return Collection|Friendship[]
*/
public function getFriendships(): Collection
{
return $this->friendships;
}
public function addFriendship(Friendship $friendship): self
{
if (!$this->friendships->contains($friendship)) {
$this->friendships[] = $friendship;
$friendship->setSender($this);
}
return $this;
}
public function removeFriendship(Friendship $friendship): self
{
if ($this->friendships->removeElement($friendship)) {
// set the owning side to null (unless already changed)
if ($friendship->getSender() === $this) {
$friendship->setSender(null);
}
}
return $this;
}
Arleigh 确实是正确的。我做错的是设置了相同的名称,即 Friendships
,同时更新我的 friendship
实体以获得用户中的两个关系,无论他是 sender
还是 recipient
。我认为这会让我更容易地在我的控制器和 twig 模板中获得与用户相关的所有 friendships
,无论它们是 recipient
还是 sender
但最后,所有它确实让一切都出错了。
我通过在我的用户中有两个单独的属性来修复它,friendshipRequestsSent
(由 Friendship
实体的 sender
字段映射)和 friendshipRequestsReceived
(映射通过 Friendship
实体的 recpient
字段)以及相关属性的方法和类型。这就是我现在 User
实体中的样子
/**
* @ORM\OneToMany(targetEntity=Friendship::class, mappedBy="sender", orphanRemoval=true)
*/
private $friendshipRequestsSent;
/**
* @ORM\OneToMany(targetEntity=Friendship::class, mappedBy="recipient", orphanRemoval=true)
*/
private $friendshipRequestsReceived;
public function __construct()
{
$this->userSkills = new ArrayCollection();
$this->experiences = new ArrayCollection();
$this->missions = new ArrayCollection();
$this->friendshipRequestsSent = new ArrayCollection();
$this->friendshipRequestsReceived = new ArrayCollection();
}
/**
* @return Collection|Friendship[]
*/
public function getFriendshipRequestsSent(): Collection
{
return $this->friendshipRequestsSent;
}
public function addFriendshipRequestSent(Friendship $friendship): self
{
if (!$this->friendshipRequestsSent->contains($friendship)) {
$this->friendshipRequestsSent[] = $friendship;
$friendship->setSender($this);
}
return $this;
}
public function removeFriendshipRequestSent(Friendship $friendship): self
{
if ($this->friendshipRequestsSent->removeElement($friendship)) {
// set the owning side to null (unless already changed)
if ($friendship->getSender() === $this) {
$friendship->setSender(null);
}
}
return $this;
}
/**
* @return Collection|Friendship[]
*/
public function getFriendshipRequestsReceived(): Collection
{
return $this->friendshipRequestsReceived;
}
public function addFriendshipRequestReceived(Friendship $friendship): self
{
if (!$this->friendshipRequestsReceived->contains($friendship)) {
$this->friendshipRequestsReceived[] = $friendship;
$friendship->setSender($this);
}
return $this;
}
public function removeFriendshipRequestReceived(Friendship $friendship): self
{
if ($this->friendshipRequestsReceived->removeElement($friendship)) {
// set the owning side to null (unless already changed)
if ($friendship->getSender() === $this) {
$friendship->setSender(null);
}
}
return $this;
}
这就是我的 Friendship
实体 sender
和 recipient
属性的声明方式
/**
* @ORM\ManyToOne(targetEntity=User::class, inversedBy="friendshipRequestsSent")
* @ORM\JoinColumn(nullable=false)
*/
private ?User $sender;
/**
* @ORM\ManyToOne(targetEntity=User::class, inversedBy="friendshipRequestsReceived")
* @ORM\JoinColumn(nullable=false)
*/
private ?User $recipient;