如何将父实体传递给 Symfony 中的表单?
How do you pass the parent entity to a form in Symfony?
假设我有两个实体:post
和 comment
。每个post
可以有很多comments
。现在,假设我有一个评论表。它应该接受用户输入并将其存储在数据库中。
简单的东西。至少,它应该是,但我无法让它工作。
如何在创建评论(子)时引用 post(父)? 我尝试手动将 post_id
传递给评论表单作为隐藏字段,但收到一个错误,抱怨 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
实体,而不仅仅是 ID。试试这个:
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');
}
评论类型
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
}
这段代码对我有用:
CommentController.php
正如上面 flint 所建议的,您只需要传递实际的 Post 实体,而不仅仅是 id。那么如果你有这个错误 "Unable to guess how to get a Doctrine instance from the request information for parameter "post"
这是因为你需要在 new_comment 的路径中添加 post slug 路线。 ParamConverter 被隐式调用,它需要这个 slug {post} 与您用于 post[= 的名称相同33=]函数中的参数。
/**
* @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关系,手动设置ID了。
不要输入表单域,
例如
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.
如果您转到您的评论实体 (App\Entity\Comment),您会看到您的 class 将父 post 引用为 Post Class (App\Entity\Post) 而不是 "post_id"。
在您的物理数据库和实体 class 中执行 link 并在您的 [=38] 中添加一个 post_id 字段的是 ORM(本例中的原则) =].
这就是 ORM(对象关系模型)的用途。您不应再将 Post 和 Comment 视为 Sql table,而应将其视为 Classes (OOP).
因此,我想添加与 someParent 相关的评论,我应该这样做:
$comment = new Comment();
$comment->setPost($post);
其中 $post 是 class Post 的实例。
假设我有两个实体:post
和 comment
。每个post
可以有很多comments
。现在,假设我有一个评论表。它应该接受用户输入并将其存储在数据库中。
简单的东西。至少,它应该是,但我无法让它工作。
如何在创建评论(子)时引用 post(父)? 我尝试手动将 post_id
传递给评论表单作为隐藏字段,但收到一个错误,抱怨 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
实体,而不仅仅是 ID。试试这个:
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');
}
评论类型
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
}
这段代码对我有用:
CommentController.php
正如上面 flint 所建议的,您只需要传递实际的 Post 实体,而不仅仅是 id。那么如果你有这个错误 "Unable to guess how to get a Doctrine instance from the request information for parameter "post"
这是因为你需要在 new_comment 的路径中添加 post slug 路线。 ParamConverter 被隐式调用,它需要这个 slug {post} 与您用于 post[= 的名称相同33=]函数中的参数。
/**
* @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关系,手动设置ID了。
不要输入表单域, 例如
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.
如果您转到您的评论实体 (App\Entity\Comment),您会看到您的 class 将父 post 引用为 Post Class (App\Entity\Post) 而不是 "post_id"。
在您的物理数据库和实体 class 中执行 link 并在您的 [=38] 中添加一个 post_id 字段的是 ORM(本例中的原则) =].
这就是 ORM(对象关系模型)的用途。您不应再将 Post 和 Comment 视为 Sql table,而应将其视为 Classes (OOP).
因此,我想添加与 someParent 相关的评论,我应该这样做:
$comment = new Comment();
$comment->setPost($post);
其中 $post 是 class Post 的实例。