1

I am trying to manage multiple forms in the same page in Symfony 5 with the following function, but it seems that every time I try to submit a form, only the first form of the list is handled even if it is not the one that has been submitted:

class ContentController extends AbstractController
{
    /**
     * @Route("/category/edition/{content}", name="edit_category")
     */
    public function edition(Request $request, Category $content): Response
    {
        $forms = [
            "edit_category" => $this->createForm(EditCategoryType::class, $content),
            "create_post" => $this->createForm(CreatePostType::class)
        ];
        foreach($forms as $form) {
            $form->handleRequest($request);
            if($form->isSubmitted() && $form->isValid()) {
                // Always prints edit_category
                // even when that is the the create_post that is submitted
                return var_dump($form->getName());
            }
        }
        return $this->render(
            'content/edition.html.twig',
            [
                'forms' => \array_map(
                    function($form) {
                        return $form->createView();
                    },
                    $forms
                ),
                'content' => $content,
            ]
        );
    }
}

I have seen in other posts that the name of the forms can sometime raise an issue, but I have checked that the forms do have different names, and I have also tried to call handleRequest() on every form in a separate foreach loop because I have seen this done in some posts, but it (quite expectedly I must say) didn't change the behavior.

And I didn't seem to find any unanimous best practice tips about how to handle multiple forms in the same Controller in Symfony, so I was wondering what is the best way to do it, or if it would be cleaner to define a separate action route for each form in order to avoid this problem altogether.

If needed, the content/edition.html.twig file looks something like that:

{% set edit_category_form = forms['edit_category'] %}
{% set create_post_form = forms['create_post'] %}
{{ form_start(edit_category_form) }}
    {{ form_errors(edit_category_form) }}
{{ form_end(edit_category_form) }}
{{ form_start(create_post_form) }}
    {{ form_errors(create_post_form) }}
{{ form_end(create_post_form) }}

(Category is a classical Symfony entity, EditCategoryType is a form associated with the Category entity and CreatePostType is a form associated with another Symfony entity)

2
  • Would it be possible to edit your post so that the code is a runnable snippet for other users to test? Commented Jan 23, 2021 at 18:13
  • I didn't include the form and entity classes because they are not relevant but it might be better now. Commented Jan 23, 2021 at 18:32

1 Answer 1

2

After some research, it seems for some reason like it works if (and only if?) the form is build just before handling the request:

class ContentController extends AbstractController
{
    /**
     * @Route("/category/edition/{content}", name="edit_category")
     */
    public function edition(Request $request, Category $content): Response
    {
        $self = $this;
        $formBuilders = [
            "edit_category" => function() use ($self, $content) {
                return $self->createForm(EditCategoryType::class, $content);
            },
            "create_post" => function() use ($self, $content) {
                return $self->createForm(CreatePostType::class);
            },
        ];
        $forms = [];
        foreach($formBuilders as $key => $formBuilder) {
            $form = $formBuilder();
            $forms[$key] = $form;
            $form->handleRequest($request);
            if($form->isSubmitted() && $form->isValid()) {
                // Does print the name of the right form
                return var_dump($form->getName());
            }
        }
        return $this->render(
            'content/edition.html.twig',
            [
                'forms' => \array_map(
                    function($form) {
                        return $form->createView();
                    },
                    $forms
                ),
                'content' => $content,
            ]
        );
    }
}

It works but it doesn't feel like a proper way to handle this !

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.