Search code examples
phpformssymfonytwigsymfony4

symfony4 inject parameter in form


I have a Business Entity and a BusinessObject Entity, and I would like to link the BusinessObject to the current Business when I create a new BusinessObject. For example, if my route is business/{id}/object/new, I would like to have the object related with the Business (thanks to the id).

In my BusinessObject Controller, I managed to use @ParamConverter to get the Business id. In my BusinessObject Form, I put an HiddenType to my business entry because I don't want it to appear, and set data to business_ID. I struggle in configureOptions to get the business ID, I can't figure out how to get the business id from here.

BusinessObject Controller (route new):

/**
 * @Route("/{post_id}/new", name="business_object_new", methods="GET|POST")
 * @ParamConverter("business", options={"id" = "post_id"})
 */
public function new(Request $request,Business $business): Response
{
    $businessObject = new BusinessObject();

    $businessID = $business->getId();

    $form = $this->createForm(BusinessObjectType::class, $businessObject,array(
        'business_ID'=>$businessID,
    ));
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        $em = $this->getDoctrine()->getManager();
        $em->persist($businessObject);
        $em->flush();

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

    return $this->render('business_object/new.html.twig', [
        'business_object' => $businessObject,
        'business'=>$business,
        'form' => $form->createView(),
    ]);
}

BusinessObjectType:

class BusinessObjectType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
    $builder
        ->add('object',TextType::class)
        ->add('complement')
        ->add('status')
        ->add('durationExpected')
        ->add('durationAchieved')
        ->add('client')
        ->add('projectManager')
        ->add('business',HiddenType::class,array(
            'data' => $options['business_ID']

        ))
    ;
}

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults([
        'data_class' => BusinessObject::class,
        'business_ID'=>Business::class
    ]);
}
}

With this code, I get an error Expected argument of type "App\Entity\Business or null", "string" given. I think this have something to do with the function configureOptions() in my Form


Solution

  • The approach can be:

    public function new(Request $request,Business $business): Response
    {
        $businessObject = new BusinessObject();
    
        $form = $this->createForm(BusinessObjectType::class, $businessObject);
        $form->handleRequest($request);
    
        if ($form->isSubmitted() && $form->isValid()) {
            // I suppose your setter is `setBusiness`, otherwise use more suitable one
            $businessObject->setBusiness($business);
            $em = $this->getDoctrine()->getManager();
            $em->persist($businessObject);
            $em->flush();
    

    Form builder is:

    builder
        ->add('object',TextType::class)
        ->add('complement')
        ->add('status')
        ->add('durationExpected')
        ->add('durationAchieved')
        ->add('client')
        ->add('projectManager');   // No business field
    

    Another option is to embed BusinessType form into BusinessObjectType, you can read more about form embedding here.