N
N
Nikolai Egorov2019-02-18 18:34:20
symfony
Nikolai Egorov, 2019-02-18 18:34:20

What is the correct way to use common fields in Symfony forms?

All day I struggle with inheritance in forms - I do everything as it is written here https://symfony.com/doc/current/form/inherit_data_... and nothing comes out. An error is thrown 5c6ac3070f8c8809773896.png, i.e. supposedly there are no property accessor methods. But they are! I was able to get form field inheritance to work, but not as described in the doc. I will give the existing code (I will reduce it to the maximum, leaving only one property / method for clarity)
First, the model classes

/**
 * @ORM\Entity
 * @ORM\Table("menus")
 * @ORM\InheritanceType("SINGLE_TABLE")
 * @ORM\DiscriminatorColumn(name="discriminator", type="string")
 * @ORM\DiscriminatorMap({
 *     "simple" = "MenuItemSimple",
 *     "page" = "MenuItemPage",
 *     "article" = "MenuItemArticle",
 *     "category" = "MenuItemCategory"
 * })
 */
class MenuItem
{
    /**
     * @ORM\Column(type="string", length=256, nullable=true)
     */
    private $titleLink;
    public function getTitleLink(): ?string
    {
        return $this->titleLink;
    }
}

/**
 * @ORM\Entity
 */
class MenuItemPage extends MenuItem {
    /**
     * @ORM\ManyToOne(targetEntity="Page")
     */
    private $page;
    public function getEntity(): ?Page
    {
        return $this->page;
    }
}

Now the form classes are as specified in the Symfony manual
// ============= класс формы с общими полями
class MenuItemCommonType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('titleLink', TextType::class, [
                'label' => 'label.title',
                'required' => false,
            ])
            ->add('hrefLink', TextType::class, [
                'label' => 'label.href',
                'required' => false,
            ])
            ->add('iconClass', TextType::class, [
                'label' => 'label.icon_class',
                'required' => false,
            ])
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            // эту строку добавил как написано на сайте симфони
            'inherit_data' => true,
        ]);
    }
}

// =============  теперь класс формы использующей общие поля + одно свое поле
class MenuItemPageType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('commonFields', MenuItemCommonType::class, [
                'data_class' => MenuItemPage::class,
            ])
            ->add('entity', Select2EntityType::class, [
                'label' => 'label.assigned_page',
                'multiple' => false,
                'remote_route' => 'admin_page_ajax_searching',
                'class' => Page::class,
                'placeholder' => 'Select a page',
                'required' => false,
                'remote_params' => [
                    'entityClass' => urlencode(Page::class),
                    'entityId' => $options['data']->getId(),
                ],
            ])
        ;
    }

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

This code throws the above error. But I still started inheritance ... for this I changed the classes like this:
  • For a class that USES common fields, I commented out adding them via the ->add('commonFields') builder, and added the getParent() method
  • And for the form class that CONTAINS common fields - commented out the line 'inherit_data' => true
class MenuItemPageType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
//            ->add('commonFields', MenuItemCommonType::class, [
//                'data_class' => MenuItemPage::class,
//            ])
            ->add('entity', Select2EntityType::class, [
                'label' => 'label.assigned_page',
                'multiple' => false,
                'remote_route' => 'admin_category_ajax_searching',
                'class' => Page::class,
                'placeholder' => 'Select a page',
                'required' => false,
                'remote_params' => [
                    'entityClass' => urlencode(Page::class),
                    'entityId' => $options['data']->getId(),
                ],
            ])
        ;
    }

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

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

// а это кусок из класса с общими полями
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
//            'inherit_data' => true,
        ]);
    }

In the end, everything works. 5c6acefbdc96a920071084.png
I don't understand... what am I doing wrong? Why the option specified in the symphony manual does not work ... The method that I managed to start, I partially found on one of the forums (I saw that you can add the getParent () method - then a new error fell out, and eliminating it all started.).
Symfony 4.2.0

Answer the question

In order to leave comments, you need to log in

1 answer(s)
V
Vadim, 2019-02-19
@nickicool

In the initial version, you are trying to embed the form, not inherit from it. In this case, the fields would be renderable like this: form.commonFields.titleLink.
It is the second option that solves your inheritance problem

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question