Skip to content
Advertisement

ManytoMany ArrrayCollection In forms Symfony

I’m working on a Symfony project where an I have two types of User Client and EmployeSpie, both have their own entity.

When you create/edit a user you can link EmployeSpie to a CLient. That’s where is my problem, When I edit or create a user I can create a user but nothing is store inside my table which make the link between my table Client and EmployeSpie.

Here is what I’ve done:
my entity Client having this:

class Client extends User
{
    /**
     * @ORMManyToMany(targetEntity=EmployeSpie::class, mappedBy="clients", cascade={"persist"})
     */
    private $employeSpies;
 
    /**
     * @return Collection|EmployeSpie[]
     */
    public function getEmployeSpies(): Collection
    {
        return $this->employeSpies;
    }

    public function addEmployeSpy(EmployeSpie $employeSpy): self
    {
        if (!$this->employeSpies->contains($employeSpy)) {
            $this->employeSpies[] = $employeSpy;
            $employeSpy->addClientEmploye($this);
        }

        return $this;
    }

    public function removeEmployeSpy(EmployeSpie $employeSpy): self
    {
        if ($this->employeSpies->contains($employeSpy)) {
            $this->employeSpies->removeElement($employeSpy);
            $employeSpy->removeClientEmploye($this);
        }

        return $this;
    }
}

and my table EmployeSpie:

class EmployeSpie extends User
{

    /**
     * @ORMManyToMany(targetEntity=Client::class, inversedBy="employeSpies")
     */
    private $clients;

    /**
     * @return Collection|Client[]
     */
    public function getClients(): Collection
    {
        return $this->clients;
    }

    public function addClient(Client $client): self
    {
        if (!$this->clients->contains($client)) {
            $this->clients[] = $client;
        }

        return $this;
    }

    public function removeClient(Client $client): self
    {
        if ($this->clients->contains($client)) {
            $this->clients->removeElement($client);
        }

        return $this;
    }

    public function __toString()
    {
        return $this->getPrenom()." ".$this->getNom();
    }

My forms are made with a Symfony form:

class ClientType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('email')
            ->add('password')
            ->add('nom')
            ->add('prenom')
            ->add('telephone')
            ->add('fax')
            ->add('is_active')
            ->add('client_fonction')
            ->add('site')
            ->add('employeSpies', EntityType::class, array(
                'class' => EmployeSpie::class ,
                'label'     => 'Sélectionnez les emloyés rattachés à ce client',
                'expanded'  => false,
                'multiple'  => true,
            ))
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Client::class,
        ]);
    }
}

and in my Controller I’ve made the following thing:

    /**
     * @Route("/admin/clients/create", name="admin.client.new")
     * @param Request $request
     * @return RedirectResponse|Response
     */

    public function new(Request $request, UserPasswordEncoderInterface $passwordEncoder)
    {
        $client = new Client();
        $form = $this->createForm(ClientType::class, $client);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid())
        {
            $client->setRoles(array('ROLE_CUSTOMER'));
            $client->setPassword(
                $passwordEncoder->encodePassword(
                    $client,
                    $form->get('password')->getData()
                )
            );
            $this->em->persist($client);
            $this->em->flush();
            $this->addFlash('success', 'Nouveau client crée avec succès');
            $this->redirectToRoute('admin.clients.index');
        }

        return $this->render("admin/clients/create.html.twig", [
            'client' => $client,
            'form' => $form->createView()

        ]);
    }

    /**
     * @Route("/admin/clients/{id}", name="admin.client.edit", methods="GET|POST")
     * @param Client $client
     * @return Response
     */
    public function edit(Client $client,Request $request, UserPasswordEncoderInterface $passwordEncoder)
    {
        $form = $this->createForm(ClientType::class, $client);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid())
        {
            $clientEmploye = $request->request->get('client');
            $clientEmploye = $clientEmploye['employeSpies'];

            $client->setPassword(
                $passwordEncoder->encodePassword(
                    $client,
                    $form->get('password')->getData()
                )
            );
            foreach ($form->get('employeSpies')->getData() as $employe){
                $client->addEmployeSpy($employe);
            }


            $client->setRoles(array('ROLE_CUSTOMER'));
            $this->em->flush();
            $this->addFlash('success', 'Nouveau client modifié avec succès');
            $this->redirectToRoute('admin.clients.index');
        }

        return $this->render("admin/clients/edit.html.twig", [
            'client' => $client,
            'form' => $form->createView()
        ]);
    }

Si my user is created or edited normally but I did not store the link for employeSpies in my form. Do you have any idea why?

Advertisement

Answer

I found the answer to my problem. @Jakumi was right but few other cha ges were needed.

In my client Entity I has to change :

    public function addEmployeSpy(EmployeSpie $employeSpy): self
    {
        if (!$this->employeSpies->contains($employeSpy)) {
            $this->employeSpies[] = $employeSpy;
            $employeSpy->addClientEmploye($this);
        }

        return $this;
    }

to :

    public function addEmployeSpy(EmployeSpie $employeSpy): self
    {
        if (!$this->employeSpies->contains($employeSpy)) {
            $this->employeSpies[] = $employeSpy;
            $employeSpy->addClient($this);
        }

        return $this;
    }

Same thing for the remove.

public function removeEmployeSpy(EmployeSpie $employeSpy): self
    {
        if ($this->employeSpies->contains($employeSpy)) {
            $this->employeSpies->removeElement($employeSpy);
            $employeSpy->removeClientEmploye($this);
        }

        return $this;
    }

to :

public function removeEmployeSpy(EmployeSpie $employeSpy): self
    {
        if ($this->employeSpies->contains($employeSpy)) {
            $this->employeSpies->removeElement($employeSpy);
            $employeSpy->removeClient($this);
        }

        return $this;
    }

But after the other change in my ClientType :

            ->add('employeSpies', EntityType::class, array(
                'class' => EmployeSpie::class ,
                'by_reference' => false,
                'label'     => 'Sélectionnez les employés rattachés à ce client',
                'expanded'  => false,
                'multiple'  => true,
            ))

I need to add the 'by_reference' => false,to make it works.

Because of this Symfony will not try to find the “setClient” method but to find addClient method

Hope it could help later some other persons 🙂

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement