Я не могу заставить текстовое поле отображаться внутри моей формы при объединении двух объектов. Пожалуйста, без javascript, я видел метод javascript с коллекциями.
Логика заключается в том, что пользователь должен добавить заголовок в форму, а затем добавить текст в текстовое поле. Когда пользователь отправляет сообщение, поток вводится с использованием заголовка, а идентификатор потока используется для добавления к нему сообщения (содержимого текстового поля).
Пример формы:
Я считаю, что этого достаточно для вывода, если он правильно настроен с помощью двух классов типа.
{{ form_start(forum_thread_form) }}
{{ form_widget(forum_thread_form) }}
{{ form_end(forum_thread_form) }}
Код:
Сущности
Thread.php
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type = "integer")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity = "App\Entity\Account", inversedBy = "forum_posts")
* @ORM\JoinColumn(nullable=false)
*/
private $account;
/**
* @ORM\ManyToOne(targetEntity = "App\Entity\Category", inversedBy = "forum_threads")
* @ORM\JoinColumn(nullable=false)
*/
private $category;
/**
* @ORM\Column(type = "string", length=128, nullable=true)
* @Assert\NotBlank()
*/
private $title;
/**
* @ORM\OneToMany(targetEntity = "App\Entity\Post", mappedBy = "thread")
*/
private $posts;
public function __construct()
{
$this->posts = new ArrayCollection();
}
## getters and setters.. some ommitted ##
/**
/*
* @return mixed
*/
public function getPosts()
{
return $this->posts;
}
/**
* @param mixed $posts
*/
public function setPosts($posts): void
{
$this->posts = $posts;
}
Post.php
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type = "integer")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity = "App\Entity\Account", inversedBy = "forum_posts")
* @ORM\JoinColumn(nullable=false)
*/
private $account;
/**
* @ORM\ManyToOne(targetEntity = "App\Entity\Thread", inversedBy = "posts")
* @ORM\JoinColumn(nullable=true)
*/
private $thread;
/**
* @ORM\Column(type = "text")
* @Assert\NotBlank()
*/
private $content;
## GETTERS AND SETTERS, some ommitted ##
/**
* @return mixed
*/
public function getThread()
{
return $this->thread;
}
/**
* @param mixed $thread
*/
public function setThread($thread): void
{
$this->thread = $thread;
}
/**
* @return mixed
*/
public function getContent()
{
return $this->content;
}
/**
* @param mixed $content
*/
public function setContent($content): void
{
$this->content = $content;
}
PostType.php
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('content', TextareaType::class)
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Post::class,
));
}
ThreadType.php
public function __construct(){
$this->posts = new ArrayCollection();
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title', TextType::class);
$builder->add('content', CollectionType::class, array(
'entry_type' => PostType::class,
'entry_options' => array('label' => false),
));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Thread::class,
));
}
ForumController.php
$forum_thread = new Thread();
$forum_thread_form = $this->createForm(ThreadType::class,$forum_thread);
$forum_thread_form->handleRequest($request);
if ($forum_thread_form->isSubmitted() && $forum_thread_form->isValid()) {
$forum_thread = $forum_thread_form->getData();
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($forum_thread);
$entityManager->flush();
}
$forum_thread_form = $forum_thread_form->createView();
return $this->render('forum/threads.html.twig',compact('forum_thread_form'));
@ShaithyaKannan добавил код контроллера.






Отредактируйте свою ветку
{{ form_start(forum_thread_form) }}
{{ form_row(forum_thread_form.title) }}
{% for contentField in forum_thread_form.posts %}
{{ form_row(contentField.content) }}
{% endfor %}
{{ form_end(forum_thread_form) }}
Это все еще не сработало, мне пришлось установить "mapped" в false в ThreadType, а затем сохранить сообщение отдельно в контроллере, не смог сделать это сразу. тогда вывод был простым, для оператора не требовалось.
@Darius Значит ли это, что вы решили свою проблему?
Пока нет, обязательные поля не проверяются. Так что найденный мной метод работает некорректно. Я попробую метод DTO, на который ответил tarl выше.
Я бы просто использовал single formtype + DTO для создания этой формы, а после подтверждения submit + просто создал эти необходимые сущности из этого DTO и сохранил + сбросил их в базу данных.
Когда я использую этот метод и создаю форму в контроллере, я делаю $ this-> createForm (ThreadType :: class, $ forum_thread) или без $ forum_thread? Я предполагаю, что $ forum_thread больше не требуется, поскольку он не привязан к сущности.
Сначала в ThreadType измените content на posts:
$builder->add('posts', CollectionType::class, array(
'entry_type' => PostType::class,
'entry_options' => array('label' => false),
));
Затем измените код в своем действии:
$forum_thread = new Thread();
$post = new Post();
$forum_thread->setPosts([$post]);
$forum_thread_form = $this->createForm(ThreadType::class, $forum_thread);
$forum_thread_form->handleRequest($request);
if ($forum_thread_form->isSubmitted() && $forum_thread_form->isValid()) {
$forum_thread = $forum_thread_form->getData();
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($post);
$entityManager->persist($forum_thread);
$entityManager->flush();
}
Это работает:
getPosts используется для заполнения поля "сообщения" CollectionType новым PostType.Технически это правильный ответ, и он работает, в итоге я использовал гибрид этого и DTO.
Не могли бы вы связать свой контроллер?