1

I use Symfony 4.2 with Doctrine and I want to create fixtures with ManyToMany relationships with two entities :

  • Organization
  • Project

But when I load fixtures the join table (organization_project) is always empty. So, I don't know if my relationships is good.

For resume :

  • Many organizations have many projects
  • Many projects have many organizations

Database view

database view

Here my Organization entity

class Organization
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    ...

    /** 
     * @ORM\ManyToMany(targetEntity="App\Entity\Project", mappedBy="organizations")
     */
    private $projects;

    /**
     * @return Collection|Project[]
     */
    public function getProjects(): Collection
    {
        return $this->projects;
    }

    public function addProject(Project $project): self
    {
        if (!$this->projects->contains($project)) {
            $this->projects[] = $project;
            $project->addOrganization($this);
        }

        return $this;
    }

    public function removeProject(Project $project): self
    {
        if ($this->projects->contains($project)) {
            $this->projects->removeElement($project);
            $project->removeOrganization($this);
        }

        return $this;
    }
}

Here my Project entity :

class Project
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    ...

    /** 
     * @ORM\ManyToMany(targetEntity="App\Entity\Organization", inversedBy="projects")
     */
    private $organizations

    /**
     * @return Collection|Organization[]
     */
    public function getOrganizations(): Collection
    {
        return $this->organizations;
    }

    public function addOrganization(Organization $organization): self
    {
        if (!$this->organizations->contains($organization)) {
            $this->organizations[] = $organization;
        }

        return $this;
    }

    public function removeOrganization(Organization $organization): self
    {
        if ($this->organizations->contains($organization)) {
            $this->organizations->removeElement($organization);
        }

        return $this;
    }

}

Here my Organization fixture :

class OrganizationFixtures extends Fixture implements DependentFixtureInterface
{
    public const ORGANIZATION_REFERENCE = 'organization-';

    public function load(ObjectManager $manager)
    {
        $organization = new Organization();
        $this->addReference(self::ORGANIZATION_REFERENCE.'0', $organization);
        $organization->addProject($this->getReference('project-0'));

        $manager->persist($organization);
        $manager->flush();
    }

     public function getDependencies()
    {
        return array(
            ProjectFixtures::class
        );
    }
} 

Here my Project fixture :

class ProjectFixtures extends Fixture
{
    public const PROJECT_REFERENCE = 'project-';

    public function load(ObjectManager $manager)
    {
        $project = new Project();
        $this->addReference(self::PROJECT_REFERENCE.'0', $project);

        $manager->persist($project);
        $manager->flush();
    }
} 

Thank you,

Bonsai
  • 346
  • 3
  • 17
  • is maybe your table emprty? can u give as more info in which point is failing? – Oscar Jun 18 '19 at 09:25
  • In my join table (organization_project), the data don't appear after I load my fixtures. Besides, I have no error in my console. I up my post with database screen – Bonsai Jun 18 '19 at 09:35
  • yes but your Organization_project table is empty. Maybe the join does not find any record? – Oscar Jun 18 '19 at 10:21
  • Thank you I resolve my problem. My organization entity wasn't owning side – Bonsai Jun 18 '19 at 11:47

1 Answers1

1

Your Organization is not owning side of the relationship. It does not hold knowledge of joining table (in ManyToOne it would be about who is holding foreign key). Also you don't specify cascading on persist, so associated entities on not owning side won't be persisted. So for your current fixture structure best association direction would be like this.

class Organization
{
...

    /** 
     * @ORM\ManyToMany(targetEntity="App\Entity\Project", inversedBy="organizations", cascade={"persist"})
     * @ORM\JoinTable(name="organization_project") # this one is not necessary
                                                       putting here for reference
     */
    private $projects;
...
]
class Project
{
...
    /** 
     * @ORM\ManyToMany(targetEntity="App\Entity\Organization", mappedBy="projects", cascade={"persist"})
     */
    private $organizations;
...
}
Ludo
  • 484
  • 2
  • 9
  • It works, thank you! So if I understood, in ManyToMany we have two owner side and when we use inversedBy in entity, this entity is owner ? – Bonsai Jun 18 '19 at 11:45
  • 1
    yes, though the not owning side can be still persisted when using `cascade={"persist"}`, but by logic of your fixture it's better to have owning side on `Organization` – Ludo Jun 18 '19 at 13:00