to nie jest kwestia symfony, tylko zasad dobrego programowania. spaghetti możesz tworzyć w kazdym fw, w symfony również

@damianooo:
stwórz formularz osobiście do sprawy podchodze tak, że:
- moje encje nie maja setterów, parametry podaję do konstruktora tylko przy utworzeniu, wymusza to tworzenie metod z logiką, które sprawiają, że encja nie jest "anemiczna"
- tworzę sobie klase formularza opartą o klasę DTO
- tworzę sobie prostą klasę DTO, którą wpinam w formularz; zawiera ona publiczne pola np. kolekcje itd (wiem, ze DTO nie powinno zawierac encji, tylko id's ale w moich przypadkach jest to pomijalne - nie serializuję dto i nie pcham po api)
- tworzę serwis implementujący konkretną ścieżkę działania (przypadek użycia), zapodaje jej wszystkie potrzebne zależności i w jego metodzie handle zawieram logikę - utworzenie, obrobienie i zapis do bazy. oczywiście TDD, więc mam od razu otestowany kod; na koniec działania rzucam event, że działanie wykonane lub exception
- tworzę sobie factory dla encji (jedna dla match i druga dla type), dzięki temu mam w systemie jedno centralne miejsce, gdzie encje są tworzone i nigdzie indziej nie ma czegoś takiego jak new Match itp; robie w niej metodę createEntityFromCommand, która DTO konwertuje do encji
- w kontrolerze: tworzę formularz, wciskam w niego DTO, populuje DTO requestem, robię walidację DTO a nie encji (trzymam jej zasady w validation.yml), jesli valid to na utworzonym serwisie robię po prostu ->handle($command), przekazuje formularz do widoku i np. ustawiam flash dla usera.
voila. wszystko odizolowane i otestowane, a ten sam kod moge wykorzystać na stronie, w api czy commandzie bez różnicy.
/**
* @Route("/rejestracja.html", name="evento_register")
* @Template()
*/
public function registerAction(Request $request)
{
$response = new Response(null, 200);
$createCommand = new CreateWorkshop();
$createCommand->lessons = [new CreateLesson()];
$form = $this->createForm("register_workshops_form_type", $createCommand, [
"action" => $this->generateUrl("evento_register"),
"method" => "POST",
]);
if($request->isMethod("POST"))
{
$form->handleRequest($request);
if($form->isValid())
{
$this->get("tactician.commandbus")->handle($form->getData());
$this->addFlash("success", "Dziękujemy za dodanie nowej informacji, po weryfikacji przez moderatora pojawi się w bazie");
return $this->redirectToRoute("evento_homepage");
} else {
$response->setStatusCode(400);
}
}
return $this->render("AppBundle:Default:register.html.twig", [
"form" => $form->createView(),
], $response);
}
Jak chcesz sobie podejrzeć, to mam taką tu małą appkę, nie zastosowałem wydzielenia klas domeny i aplikacji ani TDD ze względu na wielkość, ale to chyba identyczny przypadek jak Twoj - formularz z jedną kolekcją
https://github.com/uirapuru/evento/tree/master/src/AppBundle