Sobes.tech
Middle+

Doctrine'da 'has many through' ilişkisi nasıl uygulanır?

sobes.tech yapay zeka

AI'dan gelen yanıt

Doctrine2'de "has many through" ilişkisi, açıkça bir ara varlık (join entity) oluşturarak uygulanır, bu da iki diğer varlığı Many-to-One ilişkileriyle bağlar.

  1. Üç sınıf varlık oluşturulur: Kaynak, Hedef ve Ara (JoinEntity).

  2. Ara varlık (örneğin, "User, UserGroup aracılığıyla birçok Group'a sahip" için UserGroup), iki alan içerir ve bunlar Kaynak (User) ve Hedef (Group) varlıklarına Many-to-One ilişkileridir.

  3. Kaynak ve Hedef varlıklar, Ara varlıkla One-to-Many ilişkiye sahiptir.

  4. Hedef varlıklara, Kaynak üzerinden erişimi kolaylaştırmak için (örneğin, bir User için tüm Group'ları almak), Kaynak varlıkta bir yöntem eklenebilir, bu yöntem Ara varlıkları filtreler.

İşte yapı örneği:

// 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; // Ara varlığa ilişki

    public function __construct()
    {
        $this->userGroups = new ArrayCollection();
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    /**
     * Kullanıcının gruplarını, ara varlık aracılığıyla al.
     * Bu, "has many through" ile eşdeğerdir.
     * Not: Bu koleksiyonu ihtiyaçlarınıza göre verimli şekilde almanız gerekebilir.
     */
    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)) {
            // Sahip olan tarafı null yap (zaten değiştirilmediyse)
            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; // Ara varlığa ilişki

    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)) {
            // Sahip olan tarafı null yap (zaten değiştirilmediyse)
            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')] // Tablo adının örneği
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; // User'a Many-to-One

    #[ORM\ManyToOne(targetEntity: Group::class, inversedBy: 'userGroups')]
    #[ORM\JoinColumn(nullable: false)]
    private ?Group $group = null; // Group'a Many-to-One

    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;
    }
}

Bu yaklaşım, ek bir varlık oluşturmayı gerektirse de, ilişkilerin verileri üzerinde tam kontrol sağlar ve ara tabloya ek alanlar (örneğin, kullanıcının gruba katılma tarihi) eklemeyi kolaylaştırır.