Home > Back-end >  Symfony project - Doctrine Self-Reference issue
Symfony project - Doctrine Self-Reference issue

Time:01-24

I am working on a Symfony 6.1 project and have the following situation. I have an entity called "MaterialGroup". A material group can be in a parent-child relation with itself so one material group can have some "subGroups" and one subGroup can only belong to one "upperGroup". So basically it is ay One-to-Many Relationship.

Now, when I want to update the relations in the "new" or "edit" function of the controller in symfony it basically does not work. I do not get any errors and the if I use the function "dd()" in order to preview the parent materialGroup, I can see the subGroups that should be mapped. However after the flush nothing happens.

Here is my current code:

Entity

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

    /**
     * @ORM\ManyToOne(targetEntity=MaterialGroup::class, inversedBy="subGroups")
     */
    private $parentMaterialGroup;

    /**
     * @ORM\OneToMany(targetEntity=MaterialGroup::class, mappedBy="parentMaterialGroup")
     */
    private $subGroups;

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

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

    public function getParentMaterialGroup(): ?self
    {
        return $this->parentMaterialGroup;
    }

    public function setParentMaterialGroup(?self $parentMaterialGroup): self
    {
        $this->parentMaterialGroup = $parentMaterialGroup;

        return $this;
    }


    /**
     * @return Collection<int, self>
     */
    public function getSubGroups(): Collection
    {
        return $this->subGroups;
    }

    public function addSubGroup(self $subGroup): self
    {
        if (!$this->subGroups->contains($subGroup)) {
            $this->subGroups[] = $subGroup;
            $subGroup->setParentMaterialGroup($this);
        }

        return $this;
    }

    public function removeSubGroup(self $subGroup): self
    {
        if ($this->subGroups->removeElement($subGroup)) {
            // set the owning side to null (unless already changed)
            if ($subGroup->getParentMaterialGroup() === $this) {
                $subGroup->setParentMaterialGroup(null);
            }
        }

        return $this;
    }  
}

Edit function in Controller

    #[Route('/{id}/edit', name: 'edit', methods: ['GET', 'POST'])]
    public function edit(Request $request, MaterialGroup $materialGroup, EntityManagerInterface $entityManager): Response
    {
        $form = $this->createForm(MaterialGroupType::class, $materialGroup);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $data = $request->request->all();

            $subGroups = [];
            if(isset($data["material_group"]["subGroups"]))
                $subGroups = $data["material_group"]["subGroups"];

            //Get the material group objects for all the subGroups
            $requestSubGroups = [];
            foreach($subGroups as $value) {
                $requestSubGroups[] = $this->materialGroupRepository->find($value);
            }

            //"Insert" the new subGroup relations
            foreach($requestSubGroups as $subGroup) {
               $materialGroup->addSubGroup($subGroup);
            }

            //This dd() leads to the object you can see after the code for the edit function in this post
            dd($materialGroup);
            
            $this->entityManager->flush();

            return $this->redirectToRoute($this->routeName.'_index', [], Response::HTTP_SEE_OTHER);
        }

        return $this->renderForm($this->routeName.'/edit.html.twig', [
            $this->routeName => $materialGroup,
            'form' => $form,
        ]);
    }

This object shows the subGroups that should be mapped to this materialGroup before the flush. And after the flush they are not mapped:

App\Entity\Tables\MaterialGroup {#1116 ▼
  -id: 982
  -parentMaterialGroup: null
  -subGroups: Doctrine\ORM\PersistentCollection {#1324 ▼
    #collection: Doctrine\Common\Collections\ArrayCollection {#1335 ▼
      -elements: array:5 [▼
        0 => App\Entity\Tables\MaterialGroup {#1707 ▶}
        1 => App\Entity\Tables\MaterialGroup {#1729 ▶}
        2 => App\Entity\Tables\MaterialGroup {#1750 ▶}
        3 => App\Entity\Tables\MaterialGroup {#1771 ▶}
        4 => App\Entity\Tables\MaterialGroup {#1885 ▶}
      ]
    }
    #initialized: true
    -snapshot: array:4 [ …4]
    -owner: App\Entity\Tables\MaterialGroup {#1116}
    -association: array:15 [ …15]
    -em: Doctrine\ORM\EntityManager {#452 …11}
    -backRefFieldName: "parentMaterialGroup"
    -typeClass: Doctrine\ORM\Mapping\ClassMetadata {#1009 …}
    -isDirty: true
  }
}

Can anyone tell me what I am misunderstanding or doing wrong here?

CodePudding user response:

tried setParentMaterialGroup function instead of addSubGroup after getting the subGroup:

$subGroup->setParentMaterialGroup($materialGroup);

CodePudding user response:

Can anyone tell me what I am misunderstanding or doing wrong here?

this is:

A material group can be in a parent-child relation with itself

If u want relations u should create different entities for set relations between them.

  • Related