Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

Symfony 5 : handling multiple forms in one controller

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)

question from:https://stackoverflow.com/questions/65862450/symfony-5-handling-multiple-forms-in-one-controller

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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 !


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...