簡體   English   中英

擁有方的一對多單向查找原則

[英]Doctrine one-to-many UNIDIRECTIONAL find on owning side

問題定義

因此,鑒於 Doctrine 文檔的這一部分(以及許多其他關於雙向關聯和持久性問題的文章),我有一個單向的一對多關聯。 它介於ClubStaff之間。 從領域邏輯來看, Club應該擁有Staff 例如,如果我使用文檔存儲, Staff將是Club的成員。 在 99.9% 的域案例中,我有一個club並想要一份其員工名單。

但是,我無法在 Doctrine 中實現這個想法。 因為在教義中,一對多關系只有相反的一面。 所以即使在概念上,以下實體定義也是錯誤的,但我不知道更好。

實體代碼

<?php

class Club
{
    /**
     * @ORM\Id
     * @ORM\Column(type="uuid", unique=true)
     * @ORM\GeneratedValue(strategy="CUSTOM")
     * @ORM\CustomIdGenerator(class="Ramsey\Uuid\Doctrine\UuidGenerator")
     */
    public ?UuidInterface $id;

    /**
     * @ORM\Column(type="string", name="name")
     */
    public string $name;

    /**
     * @ORM\OneToMany(targetEntity="Staff", mappedBy="club")
     */
    public Collection $staff;

    public function __construct(string $name)
    {
        $this->id       = Uuid::uuid4();
        $this->name     = $name;
        $this->staff    = new ArrayCollection();
    }

    public function addStaff(Staff $staff): void
    {
        $this->staff->add($staff);
    }

}

class Staff
{
    public const ROLE_OWNER = 'owner';

    /**
     * @ORM\Id
     * @ORM\Column(type="uuid", unique=true)
     * @ORM\GeneratedValue(strategy="CUSTOM")
     * @ORM\CustomIdGenerator(class="Ramsey\Uuid\Doctrine\UuidGenerator")
     */
    public ?UuidInterface $id;

    /**
     * @ORM\Column(type="string", name="user_id")
     */
    public string $userId;

    /**
     * @ORM\Column(type="string", name="role")
     */
    public string $role;

    public function __construct(string $userId, string $role)
    {
        $this->id     = Uuid::uuid4();
        $this->userId = $userId;
        $this->role   = $role;
    }
}

但真正的問題來了。 我有一個用例,我想為合適的員工找到俱樂部。 這是一個 (ONE-)MANY-ONE 問題,需要注意的是第一個不是另一個 Doctrine 實體,而是Staff實體的userId

所以我嘗試了幾種方法來獲取給定userId Club實體:

失敗的嘗試

<?php
   // 1. Naive solution, just try to use the `ObjectRepository`
   // Will cause: You cannot search for the association field 'Club#staff', because it is the inverse side of an association. Find methods only work on owning side associations.
$staffers = $this->em->getRepository(Staff::class)->findBy(['userId' => $ownerId]);
$clubs = $this->em->getRepository(Club::class)->findBy(['staff' => $staffers]);

   // 2. Use `QueryBuilder` naively
   // Will cause: [Semantical Error] line 0, col 131 near 'staff = s.id': Error: Invalid PathExpression. StateFieldPathExpression or SingleValuedAssociationField expected
         $qb = $this->em->createQueryBuilder();
         $query = $qb->select('c')
         ->from(Club::class, 'c')
         ->join(Staff::class, 's', Join::WITH, 'c.staff = s.id')
         ->where('s.userId = :id')
         ->setParameter('id', $ownerId)
         ->getQuery();

    // 3. Use `QueryBuilder` with knowledge if actual DB columns
    // Will cause: [Semantical Error] line 0, col 138 near 'club_id WHERE': Error: Class Staff has no field or association named club_id
         $qb = $this->em->createQueryBuilder();
         $query = $qb->select('c')
         ->from(Club::class, 'c')
         ->join(Staff::class, 's', Join::WITH, 'c.id = s.club_id')
         ->where('s.userId = :id')
         ->setParameter('id', $ownerId)
         ->getQuery();

    // 4. Create query directly
    // Will cause: [Semantical Error] line 0, col 125 near 'staff = s.id': Error: Invalid PathExpression. StateFieldPathExpression or SingleValuedAssociationField expected
                $query = $this->em->createQuery('SELECT c FROM ' . Club::class . ' c JOIN ' . Staff::class . ' s WITH c.staff = s.id WHERE s.userId = :id')->setParameter('id', $ownerId);

我在尋找什么?

  • ClubStaff之間的單向關聯,這樣我就不必擔心持久性、性能、不一致等問題。只是雙向關聯的所有問題。
  • 任何一個:
    • 實體/協會的可能返工
    • 一種檢索Club實體的方法,給定staff.userId

一個有效的解決方案,但我無法解釋為什么這個解決方案有效而其他解決方案無效。

<?php
$this->em->createQueryBuilder()
            ->select('c')
            ->from(Club::class, 'c')
            ->innerJoin(Staff::class, 's')
            ->where('s.userId = :owner')
            ->setParameter('owner', $ownerId)
            ->getQuery()
            ->getResult();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM