Home > Software engineering >  Form data keeps adding with page refresh | Symfony
Form data keeps adding with page refresh | Symfony

Time:12-30

After every page refresh, the data submitted via form keeps adding to the database and I cannot figure out why. I've checked Post/Redirect/Get pattern (https://en.wikipedia.org/wiki/Post/Redirect/Get) but could not find out how to apply it for my case. Because in my AddComment() function I use if statement to check if the form is submitted and then make redirect.

/**
 * @Route("/comments", name="app_comments")
 */
public function indexAction(Request $request, EntityManagerInterface $entityManager): Response
{

    $allComments = $this->getComments($entityManager);

    $sortedComments = $this->sortComments($allComments);

    $user = $this->getUser();

    $comment = new Comment();

    $commentForm = $this->commentForm($request, $comment);

    $this->addComment($commentForm, $comment, $user, $entityManager, $_POST['parent_id'] ?? null);
    
    $isCommentAlreadyLiked =
        $entityManager->getRepository(CommentLike::class)->countByCommentAndUser($comment, $user);

    return $this->renderForm('comments/index.html.twig',[
        'form' => $commentForm,
        'sortedComments' => $sortedComments,
        'isCommentAlreadyLiked' => $isCommentAlreadyLiked
    ]);

}

private function getComments(EntityManagerInterface $entityManager): array
{
    return $allComments = $entityManager->getRepository(Comment::class)->findAll();
}

public function addComment($form, $comment, $user, EntityManagerInterface $entityManager, ?int $parentId = null)
{

    if ($form->isSubmitted() && $form->isValid()) {

        $comment->setUser($user);
        $comment->setCreatedAt(new \DateTime());
        $comment->setParentId($_POST['parent_id'] ?? null);
        $comment = $form->getData();

        $entityManager->persist($comment);
        $entityManager->flush();

        return $this->redirectToRoute('app_comments');

    }

    return null;

}

public function commentForm(Request $request, $comment): FormInterface
{

    $form = $this->createForm(CommentType::class, $comment);

    $form->handleRequest($request);

    return $form;

}

I use redirect after the data is added to the DB as specified in Post/Redirect/Get pattern (https://en.wikipedia.org/wiki/Post/Redirect/Get) but it still doesn't work

CodePudding user response:

Your problem is that in addComment you are returning a call to a redirect() but the return is from the addComment function, once you get to the index function you do not return this response, so this code skips and basically you get to the end of the file where you call the renderForm() function.

This causes to render again your view without an actual redirect so the form object now is already filled and when you press F5 you are triggering a POST submit of the form every time.

I normally use the same function to do all the logic of the form and everything but if your code is large and prefer to splice it in function it would approach it like this:

indexAction

/**
 * @Route("/comments", name="app_comments")
 */
public function indexAction(Request $request, EntityManagerInterface $entityManager): Response
{

    $allComments = $this->getComments($entityManager);

    $sortedComments = $this->sortComments($allComments);

    $user = $this->getUser();

    $comment = new Comment();

    $commentForm = $this->commentForm($request, $comment);

    if ($form->isSubmitted() && $form->isValid()) {
        $this->addComment($commentForm, $comment, $user, $entityManager, $_POST['parent_id'] ?? null);

        return $this->redirectToRoute('app_comments');
    }
    
    $isCommentAlreadyLiked =
        $entityManager->getRepository(CommentLike::class)->countByCommentAndUser($comment, $user);

    return $this->renderForm('comments/index.html.twig',[
        'form' => $commentForm,
        'sortedComments' => $sortedComments,
        'isCommentAlreadyLiked' => $isCommentAlreadyLiked
    ]);

}

addComment

public function addComment($form, $comment, $user, EntityManagerInterface $entityManager, ?int $parentId = null)
{

        $comment->setUser($user);
        $comment->setCreatedAt(new \DateTime());
        $comment->setParentId($_POST['parent_id'] ?? null);
        $comment = $form->getData();

        $entityManager->persist($comment);
        $entityManager->flush();

}

This way you do not need to go on returning redirects or nulls depending on a condition, keep the logic on the main function and the addComment purely manages the comment.

CodePudding user response:

Is your form submitted via POST or GET method?

Also you can wrap $form->handleRequest($request); in commentForm to check if the request method is POST $request->isMethod(Request::METHOD_GET).

public function commentForm(Request $request, $comment): FormInterface
{

    $form = $this->createForm(CommentType::class, $comment);

    if ($request->isMethod(Request::METHOD_GET)){
        $form->handleRequest($request);
    }

    return $form;

}
  • Related