Symfony 4.4:多对多关联数据无法通过表单写入数据库的问题求助
嘿,先看你碰到的错误提示:
Neither the property "competences" nor one of the methods "getCompetences()", "competences()", "isCompetences()", "hasCompetences()", "__get()" exist and have public access in class "App\Entity\Competence".
这个提示已经说得很直白了——你的表单类UserCompetenceType绑定的是Competence实体,但你在表单里加了competences字段,可Competence类里根本没这个属性啊!它的多对多关联字段叫apprenant,而competences是User实体里的属性。
问题出在哪?
你要做的是给用户绑定技能,而在这个多对多关联里,User是拥有关联的一方(看注解:User的@ManyToMany用了mappedBy="apprenant",指向Competence里的关联字段),所以表单应该绑定到User实体,而不是Competence。
一步步修正
1. 改表单类UserCompetenceType
把表单的目标实体换成User,并且用正确的字段类型来渲染多对多关联:
<?php namespace App\Form; use App\Entity\User; use App\Entity\Competence; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\OptionsResolver\OptionsResolver; class UserCompetenceType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('competences', EntityType::class, [ 'class' => Competence::class, 'choice_label' => 'nom', // 下拉/复选框里显示技能名称 'multiple' => true, // 允许多选技能 'expanded' => false, // false是下拉框,true是复选框,按需选择 ]) ; } public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults([ 'data_class' => User::class, ]); } }
这里必须用EntityType,Symfony才能正确处理实体的选择和关联保存,不能直接用普通字段。
2. 控制器里的逻辑要对应
处理表单的控制器里,你要传入一个User实例(比如当前登录用户,或者从数据库查出来的用户),然后处理提交:
// 举个控制器的例子 public function addUserCompetences(Request $request, UserInterface $currentUser, EntityManagerInterface $em) { $form = $this->createForm(UserCompetenceType::class, $currentUser); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $em->persist($currentUser); $em->flush(); $this->addFlash('success', '技能已经成功添加啦!'); return $this->redirectToRoute('你的跳转路由'); } return $this->render('user/competences_form.html.twig', [ 'form' => $form->createView(), ]); }
3. 模板里正常渲染表单就行
Twig模板里这么写:
{{ form_start(form) }} {{ form_widget(form) }} <button type="submit" class="btn btn-primary">保存我的技能</button> {{ form_end(form) }}
额外检查点
- 你
User实体里的addCompetence方法已经做了双向关联($competence->addApprenant($this);这行很关键,已经写对了) - 用
php bin/console doctrine:schema:validate命令验证下数据库schema是否正确,确保中间表competence_user存在
这样改完,表单就能正确把用户选的技能保存到中间表啦!
内容的提问来源于stack exchange,提问作者Loic Dauchy

