Как передать родительский объект в форму в Symfony? - PullRequest
0 голосов
/ 05 ноября 2018

Предположим, у меня есть две сущности: 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');
}

Большое спасибо за помощь!

Ответы [ 4 ]

0 голосов
/ 04 декабря 2018

В сообщении об ошибке сказано все:

Expected argument of type "App\Entity\Post or null", "string" given.

Если вы перейдете к комментарию Entity (App \ Entity \ Comment), вы увидите, что ваш класс ссылается на родительский пост как класс сообщений (App \ Entity \ Post), а не как "post_id".

Именно ORM (в данном случае доктрина) делает ссылку в вашей физической базе данных и ваших классах сущностей и добавляет поле post_id в вашу таблицу.

Это то, для чего предназначена ORM (объектно-реляционная модель). Вам больше не следует рассматривать Post и Comment как таблицы Sql, а как классы (ООП).

Таким образом, я хочу добавить комментарий, связанный с someParent. Я должен сделать что-то вроде:

$comment = new Comment();
$comment->setPost($post);

Где $ post - это экземпляр класса Post.

0 голосов
/ 28 ноября 2018

У меня работает этот код:

CommentController.php

Как предложено выше кремнем, вам просто нужно передать фактическую сущность Post, а не только id. Тогда, если у вас есть эта ошибка "Unable to guess how to get a Doctrine instance from the request information for parameter "post", это потому, что вам нужно добавить слаг post в путь маршрута new_comment . ParamConverter вызывается неявно, и ему нужен этот слаг {post} с тем же именем, что и имя, которое вы использовали для параметра post в функции.

/**
 * @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 между двумя таблицами и вручную устанавливать идентификатор.

0 голосов
/ 04 декабря 2018

Не вставляйте в поле формы, для примера

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');
}
0 голосов
/ 05 ноября 2018

Вам просто нужно передать фактическую 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');
}

комментарийВведите

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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...