Symfony Doctrine:如何通过 getter 获取具有附加属性的关系数据

Symfony Doctrine: How to get Relation data with additional attributes through getters

我想开发一个由原则驱动的数据库应用程序,它应该描述以​​下模式。

有用户、公司和关系角色,描述用户与公司之间的关系,如 [USER X] is [ROLE X] in [COMPANY X]

我正在使用 symfony maker-bundle 创建我需要的实体。我将在本文末尾附上所有代码 post。

为了测试代码,我将公司、用户、角色以及它们之间的关系持久化到数据库中。我希望我可以使用 Company-Entity-Object 和生成的 getter getRelatedUsers() 获得所有相关用户的角色,但我得到一个空的 ArrayCollection.

这就是我在 TestController

中测试获取数据的方式
#[Route('/test', name: 'test_page')]
public function index(CompanyRepository $companyRepository): Response
{

    $companies = $companyRepository->findAll();
    dd($companies[0]->getRelatedUsers());
   
}

感谢您的帮助!

User.php

<?php
    
    namespace App\Entity;
    
    use App\Repository\UserRepository;
    use Doctrine\Common\Collections\ArrayCollection;
    use Doctrine\Common\Collections\Collection;
    use Doctrine\ORM\Mapping as ORM;
    
    /**
     * @ORM\Entity(repositoryClass=UserRepository::class)
     * @ORM\Table(name="`user`")
     */
    class User
    {
        /**
         * @ORM\Id
         * @ORM\GeneratedValue
         * @ORM\Column(type="integer")
         */
        private $id;
    
        /**
         * @ORM\Column(type="string", length=255)
         */
        private $fullName;
    
        /**
         * @ORM\OneToMany(targetEntity=UserCompanyRelation::class, mappedBy="user")
         */
        private $relatedCompanies;
    
    
        public function __construct()
        {
            $this->relatedCompanies = new ArrayCollection();
        }
    
        public function getId(): ?int
        {
            return $this->id;
        }
    
        public function getFullName(): ?string
        {
            return $this->fullName;
        }
    
        public function setFullName(string $fullName): self
        {
            $this->fullName = $fullName;
    
            return $this;
        }
    
        /**
         * @return Collection|UserCompanyRelation[]
         */
        public function getRelatedCompanies(): Collection
        {
            return $this->relatedCompanies;
        }
    
        public function addRelatedCompany(UserCompanyRelation $relatedCompany): self
        {
            if (!$this->relatedCompanies->contains($relatedCompany)) {
                $this->relatedCompanies[] = $relatedCompany;
                $relatedCompany->setUser($this);
            }
    
            return $this;
        }
    
        public function removeRelatedCompany(UserCompanyRelation $relatedCompany): self
        {
            if ($this->relatedCompanies->removeElement($relatedCompany)) {
                // set the owning side to null (unless already changed)
                if ($relatedCompany->getUser() === $this) {
                    $relatedCompany->setUser(null);
                }
            }
    
            return $this;
        }
    
    }

Company.php

<?php

namespace App\Entity;

use App\Repository\CompanyRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass=CompanyRepository::class)
 */
class Company
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

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

    /**
     * @ORM\OneToMany(targetEntity=UserCompanyRelation::class, mappedBy="company")
     */
    private $relatedUsers;


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

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

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    /**
     * @return Collection|UserCompanyRelation[]
     */
    public function getRelatedUsers(): Collection
    {
        return $this->relatedUsers;
    }

    public function addRelatedUser(UserCompanyRelation $relatedUser): self
    {
        if (!$this->relatedUsers->contains($relatedUser)) {
            $this->relatedUsers[] = $relatedUser;
            $relatedUser->setCompany($this);
        }

        return $this;
    }

    public function removeRelatedUser(UserCompanyRelation $relatedUser): self
    {
        if ($this->relatedUsers->removeElement($relatedUser)) {
            // set the owning side to null (unless already changed)
            if ($relatedUser->getCompany() === $this) {
                $relatedUser->setCompany(null);
            }
        }

        return $this;
    }

}

UserCompanyRelation.php

<?php

namespace App\Entity;

use App\Repository\UserCompanyRelationRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass=UserCompanyRelationRepository::class)
 */
class UserCompanyRelation
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity=UserCompanyRelationRole::class, inversedBy="userCompanyRelations")
     * @ORM\JoinColumn(nullable=false)
     */
    private $role;

    /**
     * @ORM\ManyToOne(targetEntity=Company::class, inversedBy="relatedUsers")
     * @ORM\JoinColumn(nullable=false)
     */
    private $company;

    /**
     * @ORM\ManyToOne(targetEntity=User::class, inversedBy="relatedCompanies")
     * @ORM\JoinColumn(nullable=false)
     */
    private $user;

    public function __construct()
    {
    }

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

    public function getRole(): ?UserCompanyRelationRole
    {
        return $this->role;
    }

    public function setRole(?UserCompanyRelationRole $role): self
    {
        $this->role = $role;

        return $this;
    }

    public function getCompany(): ?Company
    {
        return $this->company;
    }

    public function setCompany(?Company $company): self
    {
        $this->company = $company;

        return $this;
    }

    public function getUser(): ?User
    {
        return $this->user;
    }

    public function setUser(?User $user): self
    {
        $this->user = $user;

        return $this;
    }

}

UserCompanyRelationRole.php

<?php

namespace App\Entity;

use App\Repository\UserCompanyRelationRoleRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass=UserCompanyRelationRoleRepository::class)
 */
class UserCompanyRelationRole
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

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

    /**
     * @ORM\OneToMany(targetEntity=UserCompanyRelation::class, mappedBy="role")
     */
    private $userCompanyRelations;

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

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

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    /**
     * @return Collection|UserCompanyRelation[]
     */
    public function getUserCompanyRelations(): Collection
    {
        return $this->userCompanyRelations;
    }

    public function addUserCompanyRelation(UserCompanyRelation $userCompanyRelation): self
    {
        if (!$this->userCompanyRelations->contains($userCompanyRelation)) {
            $this->userCompanyRelations[] = $userCompanyRelation;
            $userCompanyRelation->setRole($this);
        }

        return $this;
    }

    public function removeUserCompanyRelation(UserCompanyRelation $userCompanyRelation): self
    {
        if ($this->userCompanyRelations->removeElement($userCompanyRelation)) {
            // set the owning side to null (unless already changed)
            if ($userCompanyRelation->getRole() === $this) {
                $userCompanyRelation->setRole(null);
            }
        }

        return $this;
    }
}

实体之间的双向映射应该使用inversed by。参见:https://www.doctrine-project.org/projects/doctrine-orm/en/2.9/reference/association-mapping.html#many-to-many-bidirectional

我找到了解决办法。我不得不在注释属性中将获取策略修改为 EAGER。我在company.php

中修改了relatedUsers注解属性
<?php

namespace App\Entity;

use App\Repository\CompanyRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass=CompanyRepository::class)
 */
class Company
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

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

    /**
     * @ORM\OneToMany(targetEntity=UserCompanyRelation::class, mappedBy="company", fetch="EAGER")
     */
    private $relatedUsers;


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

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

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    /**
     * @return Collection|UserCompanyRelation[]
     */
    public function getRelatedUsers(): Collection
    {
        return $this->relatedUsers;
    }

    public function addRelatedUser(UserCompanyRelation $relatedUser): self
    {
        if (!$this->relatedUsers->contains($relatedUser)) {
            $this->relatedUsers[] = $relatedUser;
            $relatedUser->setCompany($this);
        }

        return $this;
    }

    public function removeRelatedUser(UserCompanyRelation $relatedUser): self
    {
        if ($this->relatedUsers->removeElement($relatedUser)) {
            // set the owning side to null (unless already changed)
            if ($relatedUser->getCompany() === $this) {
                $relatedUser->setCompany(null);
            }
        }

        return $this;
    }

}