ManytoMany ArrrayCollection 形式 Symfony

ManytoMany ArrrayCollection In forms Symfony

我正在做一个 Symfony 项目,我有两种类型的用户客户端和 EmployeSpie,它们都有自己的实体。

当您 create/edit 用户时,您可以 link 将 EmployeSpie 用于客户。 这就是我的问题所在,当我编辑或创建用户时,我可以创建一个用户,但我的 table 中没有存储任何内容,这使得我的 table 客户端和 EmployeSpie 之间存在 link。

这是我所做的:
我的实体客户有这个:

class Client extends User
{
    /**
     * @ORM\ManyToMany(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;
    }
}

和我的 table EmployeSpie:

class EmployeSpie extends User
{

    /**
     * @ORM\ManyToMany(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();
    }

我的表格是用 Symfony 表格制作的:

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,
        ]);
    }
}

在我的控制器中,我做了以下事情:

    /**
     * @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 我的用户已正常创建或编辑,但我没有在我的表单中存储 link for employeSpies。你知道为什么吗?

我找到了问题的答案。 @Jakumi 是对的,但几乎不需要其他更改。

在我的客户端实体中,我必须更改:

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

        return $this;
    }

至:

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

        return $this;
    }

移除同样如此。

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

        return $this;
    }

至:

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

        return $this;
    }

但是在我的 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,
            ))

我需要添加 'by_reference' => false, 才能使其正常工作。

因为这个,Symfony 不会尝试寻找“setClient”方法,而是寻找 addClient 方法

希望以后对其他人有所帮助:)