Symfony4:使用Doctrine在单表单处理双实体,textarea不显示
解决Symfony4中Doctrine双实体表单textarea不显示的问题
我来帮你搞定这个问题,你的核心问题出在表单字段映射错误和集合未初始化这两点上,咱们一步步修正:
1. 修正ThreadType的字段映射
你在ThreadType里错误地把字段命名为content,但Thread实体和Post实体的关联属性是posts,所以必须把表单字段改成posts,才能正确关联到Post的表单类型:
// src/Form/ThreadType.php use Symfony\Component\Form\Extension\Core\Type\CollectionType; use Symfony\Component\Form\Extension\Core\Type\TextType; public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('title', TextType::class); // 把content改成posts,对应Thread实体的posts集合属性 $builder->add('posts', CollectionType::class, [ 'entry_type' => PostType::class, 'entry_options' => ['label' => false], // 因为你只需要一个Post内容,禁用删除选项 'allow_delete' => false, ]); }
2. 初始化Thread的Posts集合
CollectionType默认不会渲染任何输入框,因为新创建的Thread实例的posts集合是空的。所以在控制器里,创建Thread对象后要主动添加一个Post实例进去:
// src/Controller/ForumController.php use App\Entity\Thread; use App\Entity\Post; use App\Form\ThreadType; use Symfony\Component\HttpFoundation\Request; public function createThread(Request $request) { $forum_thread = new Thread(); // 预先添加一个Post实例到Thread的posts集合,这样表单才会渲染textarea $forum_thread->getPosts()->add(new Post()); $forum_thread_form = $this->createForm(ThreadType::class, $forum_thread); $forum_thread_form->handleRequest($request); if ($forum_thread_form->isSubmitted() && $forum_thread_form->isValid()) { $entityManager = $this->getDoctrine()->getManager(); // 给Post设置关联的Account(假设你通过登录获取当前用户) $currentAccount = $this->getUser(); foreach ($forum_thread->getPosts() as $post) { $post->setAccount($currentAccount); $post->setThread($forum_thread); // 关联当前Thread } $entityManager->persist($forum_thread); $entityManager->flush(); // 提交成功后跳转(可选) return $this->redirectToRoute('forum_thread_detail', ['id' => $forum_thread->getId()]); } return $this->render('forum/threads.html.twig', [ 'forum_thread_form' => $forum_thread_form->createView(), ]); }
3. 优化Thread实体的关联方法(可选但推荐)
给Thread实体添加addPost方法,这样可以自动维护Post和Thread的关联,简化控制器代码:
// src/Entity/Thread.php use App\Entity\Post; use Doctrine\Common\Collections\ArrayCollection; public function __construct() { $this->posts = new ArrayCollection(); } // 补充addPost方法 public function addPost(Post $post): self { if (!$this->posts->contains($post)) { $this->posts[] = $post; $post->setThread($this); // 自动设置Post的Thread关联 } return $this; } public function removePost(Post $post): self { if ($this->posts->removeElement($post)) { if ($post->getThread() === $this) { $post->setThread(null); } } return $this; }
添加后,控制器里初始化的代码可以改成:
$forum_thread->addPost(new Post());
这样就不用在提交时手动设置$post->setThread($forum_thread)了。
4. Twig模板无需修改
你的原Twig代码完全没问题,保持原样即可:
{{ form_start(forum_thread_form) }} {{ form_widget(forum_thread_form) }} <button type="submit">发布主题</button> {{ form_end(forum_thread_form) }}
这样修改后,表单就能正确渲染出标题输入框和内容textarea,提交时会先保存Thread,再保存关联的Post,自动关联Thread的ID。
内容的提问来源于stack exchange,提问作者Darius
相关产品推荐
相关产品推荐

