Home > Mobile >  How separate code from controller to Repository & Factory
How separate code from controller to Repository & Factory

Time:10-11

I'm learning symfony 5. I have a controller but I want to break the logic into a factory and a repository. I have a little problem when using FormBuilder. Without Formbuilder in the factory it passes Request, in this case via Form. It is true that this solution works with Form, but am I doing it right?

TestFactory.php with Request

class TestFactory
{   
    public function create(Request $request)
    {
        $test = new Test();
        $test->setTest1($request->get('test1');
        $test->setTest2($request->get('test2');
        return $test;
    }
}

TestController.php

class TestController extends AbstractController
{
    public function test(Request $request, TestFactory $factory, TestRepository $repository):Response
    {
        $form = $this->createForm(TestType::class);
        $form->handleRequest($request);
        
        if ($form->isSubmitted()) {
            $test = $factory->create($form);
            $repository->save($test);
        }
        return $this->render('test.html.twig', [
            'form' => $form->createView()
        ]);
    }
}

TestFactory.php

class TestFactory
{   
    public function create(Form $form)
    {
        $test = new Test();
        $test->setTest1($form->get('test1')->getData());
        $test->setTest2($form->get('test2')->getData());
        return $test;
    }
}

TestRepository.php

class TestRepository extends ServiceEntityRepository
{
    private $entityManager;
    public function __construct(ManagerRegistry $registry, EntityManagerInterface $entityManager)
    {
        parent::__construct($registry, Test::class);
        $this->entityManager = $entityManager;
    }

    public function save(Test $test)
    {
        $this->entityManager->persist($test);
        $this->entityManager->flush();
    }
}

CodePudding user response:

Symfony forms are well suited to work with all kind of underlying data like entities, dto-object, array and so on.

It depends on your use-case and business logic and your decisions (or of your team)

In your case you could use $form->getData() and pass its value further...

The most common way is to bind your FormType to a specific entity directly. Let's stick with your TestType as a Form and Test as your entity living in src/Entity/Test.php

In TestType.php you have configureOptions method


public function buildForm(FormBuilderInterface $builder, array $options){
    // Assuming you have a property named $nickname in your Test class
    $builder->add('nickname');
}

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults([
        'data_class' => Test::class, // this tells your form to bind form-fields to a specific entity
        'empty_data' => new Test(), // crete new instance, if no data was passed
    ]);
}

in your controller

public function test(Request $request, TestFactory $factory, TestRepository $repository):Response
{
    $form = $this->createForm(TestType::class); // since you dont pass object of Test as a 2nd param, form will automagicaly create new instance for you.

    $form->handleRequest($request);
    // don't forget to check for validation errors    
    if ($form->isSubmitted() && $form->isValid()) {
        $test = $form->getData(); // hier you'll get an instance of Test with all user input already set
        // so now you only have to save it to the database
        $repository->save($test);
        // do set succesefull flash-message ...
        // redirect to ...
    }
    return $this->render('test.html.twig', [
        'form' => $form->createView()
    ]);
}
  • Related