Symfony - where to store custom Form logic?

487 Views Asked by At

I'd like to know where to store some custom code which is related to form. I'm writing the Symfony app in which user can add his own category (using form of course). When user add his category the form code inside the controller check if this form is submitted and valid. If yes then user's category and the URI which is creating based on the category name are added to database. Now this whole code and logic is stored in CategoryController inside addCategory() action. Just like the following:

public function addCategory(Request $request): Response
{
    // create the whole form inside CategoryType class
    $form = $this->createForm(CategoryType::class);

    $form->handleRequest($request);
    if ($form->isSubmitted() && $form->isValid()) {

        $categories = $form->getData();
        $categories->setName(preg_replace(
            '#\s+#', ' ', $categories->getName()));

        $categories->setCategoryUri(strtolower(str_replace(
            ' ', '-', $categories->getName())));

        $this->getDoctrine()->getRepository(Categories::class)
            ->addOneCategory($categories);

        return $this->redirectToRoute('flashcard_index');
    }

    return $this->render('category/add_category.html.twig', [
        'form' => $form->createView(),
        'slug' => 'Add category'
    ]);
}

As you see inside the if statement there's code I'm writing about. First, user data are saved to $categories variable, next I'm removing more than one space using preg_replace() (in case the user enter more than one space in form field) and finally I create URI based on category name using strtolower() and str_replace() functions.

The problem is I don't know if storing this above logic inside a controller action is a good practice and if not, where to store this logic? Could you please answer me on that question? Thank you in advance for all answers!

1

There are 1 best solutions below

6
On

Then the best place to store the logic is outside your controller like you said. The question you have to ask, is "How can I test my code on the faster and easier way?"

In a separate class. Not a manager class of a thousand line, just one class AddCategorieHandler

If you want to have a decoupled code, remove the data_class from your form. If you want to get the data from your form, just call form->getData() and you will have an array.

Then You could create a message with the symfony messenger component. This message will be associated to an handler AddCategorieHandler.

Bonus, the Messenger component can call doctrine for start a transaction and flush for you.

So..In your controller, you just have to create a message, use the Messenger to dispatch it, and voilà.

And your AddCategorieHandler has all the logic you want, easy to test (no need to mock Doctrine, or functional test..)

If you want to remove a category, just create a DeleteCategoryHandler.

It's a lot of classes you have to create, but in a big project on long term, you will be happy to run your 2,000 tests in 2secs of your entire logic!