Kaip įgyvendinti 'has many through' ryšį Doctrine?
sobes.tech AI
Atsakymas iš AI
Doctrine2 santykyje "has many through" realizuojamas per aiškiai sukurtą tarpinę entitetą (join entity), kuri sujungia dvi kitas entites Many-to-One santykiais.
-
Sukuriami trys entitetų klasės: šaltinio, tikslo ir tarpinė (JoinEntity).
-
Tarpinė entitetas (pavyzdžiui,
UserGroup"User has many Group through UserGroup") turi du laukus, kurie yra Many-to-One santykiai su Šaltinio (User) ir Tikslo (Group) entitetais. -
Šaltinio ir Tikslo entitetai turi One-to-Many santykį su Tarpine entitetu.
-
Patogumui pasiekti Tikslo entitetus per Šaltinio (pavyzdžiui, gauti visas
GroupužUser) galima pridėti metodą Šaltinio entitete, kuris filtruos Tarpines entites.
Struktūros pavyzdys:
// 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; // Santykis su tarpine entitete
public function __construct()
{
$this->userGroups = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
/**
* Gauti naudotojo grupes per tarpinę entitetą.
* Tai yra "has many through" atitikmuo.
* Pastaba: priklausomai nuo poreikių, galite efektyviai gauti šią kolekciją.
*/
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)) {
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; // Santykis su tarpine entitete
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)) {
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')] // Pavyzdinis lentelės pavadinimas
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 prie User
#[ORM\ManyToOne(targetEntity: Group::class, inversedBy: 'userGroups')]
#[ORM\JoinColumn(nullable: false)]
private ?Group $group = null; // Many-to-One prie 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;
}
}
Šis požiūris, nors ir reikalauja papildomos entitetos sukūrimo, suteikia pilną kontrolę nad ryšių duomenimis ir leidžia lengvai pridėti papildomų laukų tarpinėje lentelėje (pavyzdžiui, naudotojo prisijungimo datą prie grupės).