【问题标题】:Symfony 4 | ManyToMany Relation - Could not determine access type for propertySymfony 4 |多对多关系 - 无法确定属性的访问类型
【发布时间】:2019-07-25 04:22:34
【问题描述】:

大家好,

我目前正在开发一个 Symfony 4 项目。 我在两个学说实体(Groupe 和 Contact)之间有 ManyToMany 关系,但是当我尝试创建新联系人时,出现以下错误: (我强调实体是使用 make: entity 创建的)。 提前感谢您的帮助。

例外情况: 无法确定“App\Entity\Contact”类中属性“groupe”的访问类型:“App\Entity\Contact”类中的属性“groupe”可以使用“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,
        ]);
    }
}

【问题讨论】:

  • 粘贴 ContactType 表单
  • 看起来这个错误来自表单,因为没有setGroupe(array $groups)联系,所以无法设置组。您必须创建一个 DataMapper 或添加方法才能使表单正常工作
  • 嗨 @AythaNzt 在我的 ContactType add('groupe', EntityType::class, [ 'class' => Groupe::class, 'choice_label ' => '名称', ]); } 公共函数 configureOptions(OptionsResolver $resolver) { //.. } }
  • 您可以编辑您的帖子并将其粘贴到那里以便下次清晰:P
  • @AythaNzt 大声笑,已经完成了。

标签: php symfony doctrine many-to-many


【解决方案1】:

Symfony Forms 将使用get&lt;Property&gt;set&lt;Property&gt; 来读取和写入模型数据。在您的情况下,由于您在 Contact 上没有 setGroupe() 方法,因此表单不知道在您提交表单时如何将值写回实体。

对于这种情况,Symfony 表单有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
}

【讨论】:

  • 嗨@dbrumann 谢谢你的回答。但是,我有一个问题。因为我使用 make: crud 命令生成了我的代码,所以我有这个错误是否正常?我告诉自己,属性更新的管理应该是自动的。
  • 我对 MakerBundle 不太熟悉,但在使用 ManyToMany-associations 时看起来像这样“正常”,因为它们会覆盖 setter。我不确定由此产生的表单行为是故意的还是被忽视的错误,但请随时提出问题。
  • 好的@dbrumann,感谢您的反馈。我会试试你的解决方案,我会回来找你的。
猜你喜欢
  • 2023-03-24
  • 1970-01-01
  • 2021-05-07
  • 1970-01-01
  • 2014-07-01
  • 2020-03-02
  • 2017-05-03
  • 2022-01-22
  • 1970-01-01
相关资源
最近更新 更多