Wie implementiert man die Beziehung 'has many through' in Doctrine?
sobes.tech KI
Antwort von AI
In Doctrine2 wird die Beziehung "has many through" durch die explizite Erstellung einer Zwischenentität (Join-Entity) implementiert, die zwei andere Entitäten durch Many-to-One-Beziehungen verbindet.
-
Es werden drei Entitätsklassen erstellt: Quelle, Ziel und Zwischen (JoinEntity).
-
Die Zwischenentität (z.B.
UserGroupfür "User hat viele Group durch UserGroup") enthält zwei Felder, die Many-to-One-Beziehungen zu den Entitäten Quelle (User) und Ziel (Group) sind. -
Die Entitäten Quelle und Ziel haben eine One-to-Many-Beziehung zur Zwischenentität.
-
Um den Zugriff auf die Ziel-Entitäten über die Quelle zu erleichtern (z.B. alle
Groupfür einenUserzu erhalten), kann eine Methode in der Quell-Entität hinzugefügt werden, die die Zwischenentitäten filtert.
Beispielstruktur:
// User.php
<?php
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity]
class User
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\OneToMany(targetEntity: UserGroup::class, mappedBy: 'user')]
private Collection $userGroups; // Beziehung zur Zwischenentität
public function __construct()
{
$this->userGroups = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
/**
* Erhalte die Gruppen des Benutzers über die Zwischenentität.
* Dies ist das Äquivalent zu "has many through".
* Hinweis: Sie möchten diese Sammlung je nach Bedarf effizient abrufen.
*/
public function getGroups(): Collection
{
return $this->userGroups->map(fn(UserGroup $userGroup) => $userGroup->getGroup());
}
public function getUserGroups(): Collection
{
return $this->userGroups;
}
public function addUserGroup(UserGroup $userGroup): static
{
if (!$this->userGroups->contains($userGroup)) {
$this->userGroups->add($userGroup);
$userGroup->setUser($this);
}
return $this;
}
public function removeUserGroup(UserGroup $userGroup): static
{
if ($this->userGroups->removeElement($userGroup)) {
// Setze die besitzende Seite auf null (sofern noch nicht geändert)
if ($userGroup->getUser() === $this) {
$userGroup->setUser(null);
}
}
return $this;
}
}
// Group.php
<?php
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity]
class Group
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\OneToMany(targetEntity: UserGroup::class, mappedBy: 'group')]
private Collection $userGroups; // Beziehung zur Zwischenentität
public function __construct()
{
$this->userGroups = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getUserGroups(): Collection
{
return $this->userGroups;
}
public function addUserGroup(UserGroup $userGroup): static
{
if (!$this->userGroups->contains($userGroup)) {
$this->userGroups->add($userGroup);
$userGroup->setGroup($this);
}
return $this;
}
public function removeUserGroup(UserGroup $userGroup): static
{
if ($this->userGroups->removeElement($userGroup)) {
// Setze die besitzende Seite auf null (sofern noch nicht geändert)
if ($userGroup->getGroup() === $this) {
$userGroup->setGroup(null);
}
}
return $this;
}
}
// UserGroup.php
<?php
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity]
#[ORM\Table(name: 'user_user_group')] // Beispiel für Tabellennamen
class UserGroup
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'userGroups')]
#[ORM\JoinColumn(nullable: false)]
private ?User $user = null; // Many-to-One zu User
#[ORM\ManyToOne(targetEntity: Group::class, inversedBy: 'userGroups')]
#[ORM\JoinColumn(nullable: false)]
private ?Group $group = null; // Many-to-One zu Group
public function getId(): ?int
{
return $this->id;
}
public function getUser(): ?User
{
return $this->user;
}
public function setUser(?User $user): static
{
$this->user = $user;
return $this;
}
public function getGroup(): ?Group
{
return $this->group;
}
public function setGroup(?Group $group): static
{
$this->group = $group;
return $this;
}
}
Dieser Ansatz, obwohl er die Erstellung einer zusätzlichen Entität erfordert, bietet vollständige Kontrolle über die Beziehungsdaten und erleichtert das Hinzufügen zusätzlicher Felder in die Zwischenentität (z.B. Datum, an dem der Benutzer der Gruppe beitritt).