Symfony 4 |ManyToMany Relation - не удалось определить тип доступа для свойства - PullRequest
0 голосов
/ 03 марта 2019

Привет всем,

В настоящее время я работаю над проектом в Symfony 4. У меня есть отношение ManyToMany между двумя сущностями доктрины (Groupe и Contact), однако, когда я пытаюсьдля создания нового контакта у меня возникает следующая ошибка: (я подчеркиваю, что сущности были созданы с помощью make: entity). Заранее благодарю за помощь.

Исключения: Не удалось определить тип доступа длясвойство "groupe" в классе "App \ Entity \ Contact": свойство "groupe" в классе "App \ Entity \ Contact" может быть определено с помощью методов "addGroupe ()", "removeGroupe ()", но новое значение должнобыть массивом или экземпляром \ Traversable, задано «App \ Entity \ Groupe».

// Contact.php

 namespace App\Entity;

 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
 use Symfony\Component\Validator\Constraints as Assert;

 /**
  * @ORM\Entity(repositoryClass="App\Repository\ContactRepository")
  * @ORM\Table(name="cm_f_contact")
  */

 class Contact
 {
  // .....

  /**
   * @ORM\ManyToMany(targetEntity="App\Entity\Groupe", inversedBy="contacts")
   * @Assert\Valid
   */
   private $groupe;


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


   /**
    * @return Collection|Groupe[]
    */
   public function getGroupe(): Collection
   {
     return $this->groupe;
   }

   public function addGroupe(Groupe $groupe): self
   {
     if (!$this->groupe->contains($groupe)) {
        $this->groupe[] = $groupe;
     }

    return $this;
   }

   public function removeGroupe(Groupe $groupe): self
   {
     if ($this->groupe->contains($groupe)) {
        $this->groupe->removeElement($groupe);
     }

    return $this;
   }
}

// Groupe.php

  namespace App\Entity;

  use Doctrine\Common\Collections\ArrayCollection;
  use Doctrine\Common\Collections\Collection;
  use Doctrine\ORM\Mapping as ORM;
  use Symfony\Component\Validator\Constraints as Assert;


  /**
   * @ORM\Entity(repositoryClass="App\Repository\GroupeRepository")
   * @ORM\Table(name="cm_f_group")
   */

   class Groupe
   {

    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\Contact", mappedBy="groupe")
     */
    private $contacts;


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

   /**
    * @return Collection|Contact[]
    */
   public function getContacts(): Collection
   {
     return $this->contacts;
   }

   public function addContact(Contact $contact): self
   {
     if (!$this->contacts->contains($contact)) {
        $this->contacts[] = $contact;
        $contact->addGroupe($this);
     }

    return $this;
   }

   public function removeContact(Contact $contact): self
   {
    if ($this->contacts->contains($contact)) {
        $this->contacts->removeElement($contact);
        $contact->removeGroupe($this);
    }

    return $this;
   }

}

// ContactController.php

 <?php

  namespace App\Controller;

  use App\Entity\Contact;
  use App\Form\ContactType;
  use App\Repository\ContactRepository;
  use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  use Symfony\Component\HttpFoundation\Request;
  use Symfony\Component\HttpFoundation\Response;
  use Symfony\Component\Routing\Annotation\Route;

  /**
   * @Route("/contact")
   */

   class ContactController extends AbstractController
   {

    //...

    /**
     * @Route("/new", name="contact_new", methods={"GET","POST"})
     */
     public function new(Request $request): Response
     {
      $contact = new Contact();
      $form = $this->createForm(ContactType::class, $contact);
      $form->handleRequest($request);

      if ($form->isSubmitted() && $form->isValid()) {    
        $entityManager = $this->getDoctrine()->getManager();
        $entityManager->persist($contact);
        $entityManager->flush();

        return $this->redirectToRoute('contact_index');
       }

      return $this->render('contact/new.html.twig', [
        'contact' => $contact,
        'form' => $form->createView(),
      ]);
    }
   }

ContactType.php`

    <?php

  namespace App\Form;

  use App\Entity\Contact;
  use App\Entity\Groupe;
  use Symfony\Bridge\Doctrine\Form\Type\EntityType;
  use Symfony\Component\Form\AbstractType;
  use Symfony\Component\Form\FormBuilderInterface;
  use Symfony\Component\OptionsResolver\OptionsResolver;

  class ContactType extends AbstractType
  {
    public function buildForm(FormBuilderInterface $builder, array $options)
     {
      $builder
        ->add('firstname')
        ->add('lastname')
        ->add('email')
        ->add('sms_no')
        ->add('birth_date')
        ->add('created_by')
        ->add('groupes', EntityType::class, [
            'class' => Groupe::class,
            'choice_label' => 'name',
        ])
        ;
    }

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

1 Ответ

0 голосов
/ 04 марта 2019

Symfony Forms будет использовать get<Property> и set<Property> для чтения и записи данных модели.В вашем случае, поскольку у вас нет метода setGroupe() в Контакте, форма не знает, как записать значение обратно в сущность при отправке формы.

Для этого сценария формы Symfony имеют Data Mappers .

Data Mappers отвечают за чтение и запись данных из родительских форм и в них.

В вашем случае вам, вероятно, понадобится что-токак это:

public function mapFormToData($forms, &$data)
{
    $forms = iterator_to_array($forms);
    // "groupe" is the name of the field in the ContactType form
    $groupe = $forms['groupe'];

    foreach ($groupe as $group) {
        // $data should be a Contact object
        $data->addGroup($group);
    }

    // ...Map remaining form fields to $data
}
...