1

Situation

I have a controller which handle a page edit for instance.

/**
 * Update a page
 * @ParamConverter("page", class="AcmeBundle:Page", options={"id" = "page_id"})
 */
public function editAction(Page $page, Request $request)
{
    $form = $this->createForm(PageType::class, $page);

    if ($form->handleRequest($request)->isSubmitted() && $form->isValid()) {
        $this->getDoctrine()->getManager()->flush();

        $this->addFlash('success', 'page_admin.flash.updated');

        if ($form->get('save_and_stay')->isClicked()) {
            return $this->redirect($request->headers->get('referer'));
        }
        else {
            return $this->redirectToRoute('acme_page_admin_index');
        }
    }

    return $this->render('AcmeBundle:PageAdmin:edit.html.twig', array(
        'form' => $form->createView()
    ));
}

My form include two submit buttons, one to save the Page and come back to the index, one to save the Page and stay in the edit form.

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('headline')
        ->add('body')
        ->add('save', SubmitType::class)
        ->add('save_and_stay', SubmitType::class)
    ;
}

Question

When the form is submitted, I simply check which button has been clicked and perform the right action. But I guess I need to make a service for this and I don't know exactly how. How to name it (acme.form.save_and_stay?), where to store it (AcmeBundle\Service\SaveAndStay?).

I have some difficulties to organize my Symfony app with the services and to understand when I am supposed to use them.

AlexisWbr
  • 451
  • 5
  • 18

1 Answers1

1

I don't think you need a service. You could re-write the middle part like this:

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

        [...]

        if ($form->get('save')->isClicked()) {
            return $this->redirectToRoute('acme_page_admin_index');
        }
    }
    return $this->render('AcmeBundle:PageAdmin:edit.html.twig', array(
        'form' => $form->createView()
    ));

So you would check whether the button for save-and-go-to-index was clicked - if yes, then redirect to there. Otherwise just render the form again with the values inserted.

Oliver Adria
  • 1,123
  • 11
  • 23
  • I thought the user will be able to resend the form with F5 but Symfony is smart enough to prevent it, great ! So I really don't need any service in this case. But I read that a controller should contains less than 20 lines of codes. Just with this little form, I have 12 lines of codes. What if I need to make more, like verifications and stuff ? – AlexisWbr Jun 10 '16 at 06:11
  • For checking and validation, read up on this http://symfony.com/doc/current/book/validation.html – Oliver Adria Jun 10 '16 at 06:17
  • A "hard rule" of a controller having less than 20 lines is a bit extreme I think. Controllers should be rather "thin", but I don't think dogmatically only 20 lines is a useful rule. To find out more about Services, check out http://symfony.com/doc/current/book/service_container.html - it takes some time to really understand, but just use it a few times, and I think you'll start getting the hang of it. – Oliver Adria Jun 10 '16 at 06:23
  • Yes I'm aware about Validation constraints, it is powerfull. Alright I will simply code what I have to, and if I realize that I need the same functionality twice, I'll use the services. 20 lines of code seems really hard to respect I agree, I check often the other big bundles (FOS, Sonata &co) to understand, and it seems they don't really worry about it. Thank you – AlexisWbr Jun 10 '16 at 06:43
  • Finally nop, Symfony is not smart enough, when a user hit F5, the form is re-send. So I really need a if / else verification – AlexisWbr Jun 10 '16 at 11:19
  • Well, not the nicest way, but you could then instead of ```return this->render(...)``` do a ```return $this->redirect($this->generateUrl('path_name', ['id' => $page->getId()]));``` (found via http://stackoverflow.com/a/27677651/3347365). Would this work? – Oliver Adria Jun 12 '16 at 06:46