Home > front end >  Symfony form type extension for custom types
Symfony form type extension for custom types

Time:10-21

STARTING SITUATION

I'm trying to create, with Symfony 6, a FormTypeExtension to extend my custom types.

Class hierarchy is the following:

AbstractType    <-- indeed this class is abstract
  --MyBaseType
 |    --MySubType1
 |    --MySubType2
  --MyOtherType

My FormTypeExtension:

class TranslatableTypeExtension extends AbstractTypeExtension
{
    /**
     * Should apply to MyBaseType plus MySubType1 and
     * MySubType2 by inheritance
     */
    public static function getExtendedTypes(): iterable
    {
        return [
            MyBaseType::class,
        ];
    }

    /**
     * Special option for these custom form types
     */
    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'translate_only' => false,
        ]);

        $resolver->setDefined(['translate_only']);
    }
}

My custom type classes:

class MyBaseType extends AbstractType
{
}

class MySubType1 extends MyBaseType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('blahblahblah', TextType::class, [
                'label' => 'blahblahblah',
        ])
        (etc.)
        ;
    }
}

(same for MySubType2)

In my controller:

class MySub1Controller extends AbstractController
{
    #[Route('/MySub1/{id}/translate', name: 'app_mysub1_translate')]
    public function translateMuSub1(MySub1Repository $mySub1Repository, EntityManagerInterface $entityManager, Request $request, int $id): Response
    {
        $mySub1 = $mySub1Repository->find($id);

        $form = $this->createForm(MySubType1Type::class, $mySub1, [
            'translate_only' => true,
        ]);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $mySub1 = $form->getData();
            $entityManager->persist($mySub1);
            $entityManager->flush();

            return $this->redirectToRoute('app_mysub1', ['id' => $id]);
        }

        return $this->renderForm('public/form/mysub1.html.twig', [
            'form' => $form,
        ]);
    }
}

This results is:

An error has occurred resolving the options of the form "App\Form\Type\MySub1Type": The option "translate_only" does not exist. Defined options are: (...)

CONCLUSION

This error message means that the FormTypeExtension does not apply to MySubType1: the option translate_only is not reckognized as allowed.

QUESTIONS

I see in the Symfony Form Type Extension doc that Form Extensions can be used for the classic Form Types inheriting FormType. But I see nowhere written that we cannot use it the same way for customer types inheriting AbstractType.

  1. Is it possible or not?
  2. If possible, what am I doing wrong?

Thanks in advance for your help, buddies.

CodePudding user response:

FormType inheritance is built on method getParent(). Probably, you should not extend MyBaseType but return it in getParent()

getParent() When returning a (fully-qualified) class name here, Symfony will call each method of that type (i.e. buildForm(), buildView(), etc.) and all its type extensions, before calling the corresponding method of your custom type.

https://symfony.com/doc/current/form/create_custom_field_type.html#creating-form-types-created-from-scratch


class MyBaseType extends AbstractType
{
}

class MySubType1 extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('blahblahblah', TextType::class, [
                'label' => 'blahblahblah',
        ])
        (etc.)
        ;
    }

    public function getParent()
    {
        return MyBaseType::class;
    }
}


  • Related