Предположим, у меня есть две сущности: post и comment. Каждый post может иметь несколько comments. Теперь предположим, что у меня есть форма для комментариев. Предполагается, что пользовательский ввод будет сохранен в базе данных.
Все просто. По крайней мере, так должно быть, но я не могу заставить его работать.
Как я могу ссылаться на сообщение (родительский) при создании комментария (дочернего)? Я попытался вручную передать post_id в форму комментариев как скрытое поле, но получил сообщение об ошибке с жалобой на то, что идентификатор сообщения является строкой.
Expected argument of type "App\Entity\Post or null", "string" given.
CommentType.php
public function buildForm(FormBuilderInterface $builder, array $options)
{
$post_id = $options['post_id'];
$builder->add('content', TextareaType::class, [
'constraints' => [
new Assert\NotBlank(['message' => 'Your comment cannot be blank.']),
new Assert\Length([
'min' => 10,
'minMessage' => 'Your comment must be at least {{ limit }} characters long.',
]),
],
])->add('post', HiddenType::class, ['data' => $post_id]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Comment::class,
'post_id' => NULL,
]);
}
PostController.php (здесь появляется форма комментария)
// Generate the comment form.
$comment = new Comment();
$form = $this->createForm(CommentType::class, $comment, [
'action' => $this->generateUrl('new_comment'),
'post_id' => $post_id,
]);
CommentController.php
/**
* @param Request $request
* @Route("/comment/new", name = "new_comment")
* @return
*/
public function new(Request $request, UserInterface $user)
{
// 1) Build the form
$comment = new Comment();
$form = $this->createForm(CommentType::class, $comment);
// 2) Handle the submit (will only happen on POST)
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid())
{
// 3) Save the comment!
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($comment);
$entityManager->flush();
}
return $this->redirectToRoute('homepage');
}
Большое спасибо за Вашу помощь!






Вам просто нужно передать фактическую сущность Post, а не только идентификатор. Попробуй это:
CommentController.php
public function new(Request $request, UserInterface $user, Post $post)
{
// 1) Build the form
$comment = new Comment();
$comment->setPost($post); //where $post is instance of App\Entity\Post
$form = $this->createForm(CommentType::class, $comment);
// 2) Handle the submit (will only happen on POST)
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid())
{
// 3) Save the comment!
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($comment);
$entityManager->flush();
}
return $this->redirectToRoute('homepage');
}
CommentType
public function buildForm(FormBuilderInterface $builder, array $options)
{
//don't need to set the $post here
$builder->add('content', TextareaType::class, [
'constraints' => [
new Assert\NotBlank(['message' => 'Your comment cannot be blank.']),
new Assert\Length([
'min' => 10,
'minMessage' => 'Your comment must be at least {{ limit }} characters long.',
]),
],
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Comment::class
//don't need the default here either
]);
}
Комментарий
class Comment
{
/**
* @ORM\ManyToOne(targetEntity = "App\Entity\Post")
*/
private $post;
//other vars
public function setPost(\App\Entity\Post $post): void
{
$this->post = $post;
}
public function getPost(): \App\Entity\Post
{
return $this->post;
}
//other functions
}
Спасибо за помощь. Однако это не работает. $post_id не определен в CommentType, и если я определяю его как Post, а не как идентификатор (string / int), я получаю ошибку преобразования типа.
Кроме того, у меня нет PostInterface, если за кулисами не происходит чего-то, чего я не понимаю.
Использование интерфейса - лучшая практика, но вам не обязательно, вы можете напечатать сущность. Я изменил свой ответ, чтобы также показать класс комментариев. Подробнее здесь: symfony.com/doc/current/doctrine/associations.html
Спасибо, но мой комментарий уже настроен таким образом. Проблема заключается (я полагаю) в этой строке: ->add('post', HiddenType::class, ['data' => $post_id]);. $ post_id не существует.
Тебе эта строчка не нужна, я исправил ответ. Вы устанавливаете сообщение с помощью $ comment-> setPost ($ post);
Спасибо за всю твою помощь. Однако это еще не работает. Я получаю эту ошибку: "Unable to guess how to get a Doctrine instance from the request information for parameter "post". Если я удалю параметр $ post и вместо этого вручную создаю объект Post, я получаю вместо этого эту ошибку: A new entity was found through the relationship 'App\Entity\Comment#post' that was not configured to cascade persist operations for entity [...].
На этом этапе я могу просто удалить связь Doctrine между двумя таблицами и вручную установить идентификатор. Я бы предпочел научиться делать это правильно.
Этот код работает для меня:
CommentController.php
Как было предложено флинтом выше, вам просто нужно передать фактическую сущность Post, а не только идентификатор. Тогда, если у вас есть эта ошибка "Unable to guess how to get a Doctrine instance from the request information for parameter "post", это связано с тем, что вам нужно добавить слаг Почта в путь маршрута new_comment. ParamConverter вызывается неявно, и ему нужен этот слаг {Почта} с тем же именем, что и имя, которое вы использовали для параметра Почта в функции.
/**
* @param Request $request
* @return \Symfony\Component\HttpFoundation\RedirectResponse
* @Route("/comment/new/{post}", name = "new_comment")
*/
public function new(Request $request, Post $post)
{
$comment = new Comment();
$comment->setPost($post); //where $post is instance of App\Entity\Post
$form = $this->createForm(CommentType::class, $comment);
// 2) Handle the submit (will only happen on POST)
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid())
{
// 3) Save the comment!
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($comment);
$entityManager->flush();
}
return $this->redirectToRoute('homepage');
}
PostController.php
/**
* @Route("/post/{id}", name = "get_post")
*/
public function getPostAction(Post $post)
{
// Generate the comment form.
$comment = new Comment();
$form = $this->createForm(CommentType::class, $comment, [
'action' => $this->generateUrl('new_comment', ['post' => $post->getId()]),
]);
return $this->render('listeArticles.html.twig', [
'form' => $form->createView()
]);
}
CommentType.php
class CommentType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
//don't need to set the $post here
$builder
->add('content', TextareaType::class, [
'constraints' => [
new Assert\NotBlank(['message' => 'Your comment cannot be blank.']),
new Assert\Length([
'min' => 10,
'minMessage' => 'Your comment must be at least {{ limit }} characters long.',
]),
],
])
->add('submit', SubmitType::class);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Comment::class
]);
}
}
При этом вам не нужно удалять связь Doctrine между двумя таблицами и вручную устанавливать идентификатор.
Не помещайте в поле формы, Например
public function new(Request $request, UserInterface $user)
{
// 1) Build the form
$comment = new Comment();
$form = $this->createForm(CommentType::class, $comment);
// 2) Handle the submit (will only happen on POST)
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid())
{
comment->setPostId($post_id)
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($comment);
$entityManager->flush();
}
return $this->redirectToRoute('homepage');
}
Сообщение об ошибке говорит само за себя:
Expected argument of type "App\Entity\Post or null", "string" given.
Если вы перейдете к своему комментарию Entity (App \ Entity \ Comment), вы увидите, что ваш класс ссылается на родительский пост как на Post Class (App \ Entity \ Post), а не как на «post_id».
Именно ORM (в данном случае доктрина) устанавливает связь в вашей физической базе данных и ваших классах Entity и добавляет поле post_id в вашу таблицу.
Это то, для чего нужна ORM (объектная реляционная модель). Вы должны больше рассматривать сообщения и комментарии не как таблицы Sql, а как классы (ООП).
Таким образом, я хочу добавить комментарий, связанный с someParent, я должен сделать что-то вроде:
$comment = new Comment();
$comment->setPost($post);
Где $ post - это экземпляр класса Post.
Как упоминалось в сообщении об ошибке, вам необходимо передать объект сущности вашего post_id.