Home » Php » php – Form rendering for many to many relation in symfony 4 does not work

php – Form rendering for many to many relation in symfony 4 does not work

Posted by: admin February 25, 2020 Leave a comment

Questions:

I have many to many relation between two entities Recipient and Recipient Group. I am trying to setup a form for Recipient where I must be able to add multiple Recipient Group to Recipient. But when I try to run the rendered form, I get the following error even though addXXX and removeXXX methods exist in both the classes.

Could not determine access type for property "recipientGroups" in class 
"App\Entity\Recipient": The property "recipientGroups" in class "App\Entity\Recipient" can 
be defined with the methods "addRecipientGroup()", "removeRecipientGroup()" but the new 
value must be an array or an instance of \Traversable, "App\Entity\RecipientGroup" given.

Entity/Recipient

**
 * 
@ORM\Entity(repositoryClass="App\Repository\RecipientRepository")
*/
class Recipient
{
    ...

    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\RecipientGroup", inversedBy="recipients")
     */
    private $recipientGroups;

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

    /**
     * @return Collection|RecipientGroup[]
     */
    public function getRecipientGroups(): Collection
    {
        return $this->recipientGroups;
    }

    public function addRecipientGroup(RecipientGroup $recipientGroup): self
    {
        if (!$this->recipientGroups->contains($recipientGroup)) {
            $this->recipientGroups[] = $recipientGroup;
            $recipientGroup->addRecipient($this);
        }
        return $this;
     }

     public function removeRecipientGroup(RecipientGroup $recipientGroup): self
     {
        if ($this->recipientGroups->contains($recipientGroup)) {
        $this->recipientGroups->removeElement($recipientGroup);
        $recipientGroup->removeRecipient($this);
     }

     return $this;
    }

    public function getCreatedAt(): DateTime
    {
        return $this->createdAt;
    }

    public function setCreatedAt(DateTime $createdAt): self
    {
        $this->createdAt = $createdAt;

        return $this;
    }

    public function getUpdatedAt(): DateTime
    {
        return $this->updatedAt;
    }

    public function setUpdatedAt(DateTime $updatedAt): self
    {
        $this->updatedAt = $updatedAt;

        return $this;
    }
}

Entity/RecipientGroup:

/**
 * @ORM\Entity(repositoryClass="App\Repository\RecipientGroupRepository")
 */
class RecipientGroup  
{

    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\Recipient", mappedBy="recipientGroups")
     */
    private $recipients;

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

     * @return Collection|Recipient[]
     */
    public function getRecipients(): Collection
    {
        return $this->recipients;
    }

    public function addRecipient(Recipient $recipient): self
    {
        if (!$this->recipients->contains($recipient)) {
            $this->recipients[] = $recipient;
            $recipient->addRecipientGroup($this);
        }

        return $this;
    }

    public function removeRecipient(Recipient $recipient): self
    {
        if ($this->recipients->contains($recipient)) {
             $this->recipients->removeElement($recipient);
             $recipient->removeRecipientGroup($this);
         }

         return $this;
     }
  }

form/RecipientType

class RecipientType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('fullName')
            ->add('email')
            ->add('recipientGroups', CollectionType::class, [
                'entry_type' => RecipientGroupBlockType::class,
                'entry_options' => ['label' => false],
                'allow_add' => true,
                'allow_delete' => true,
                'help' => '<a data-collection="add" class="btn btn-info btn-sm" href="#">Add Recipient Group</a>',
                'help_html' => true,
                'by_reference' => false,
            ]);
    }

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

}

form/RecipientGroupBlockType:

<?php

namespace App\Form;

use App\Entity\Recipient;
use App\Entity\RecipientGroup;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class RecipientGroupBlockType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('recipientGroups', EntityType::class,[
                'class' => RecipientGroup::class,
                'choice_label' => 'title',
                'placeholder' => 'Select an option'
            ]);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Recipient::class,
        ]);
    }
}
How to&Answers: