Как правильно сделать использование общих полей в Symfony forms?

Весь день бьюсь с наследованием в формах - делаю все как тут написано https://symfony.com/doc/current/form/inherit_data_... и ничего не выходит. Вываливается ошибка 5c6ac3070f8c8809773896.png, т.е. якобы нет методов доступа к свойствам. Но они есть! Я смог заставить работать наследование полей формы, но не так как описано в доке. Приведу имеющийся код (сокращу по максимуму оставив лишь по одному свойству/методу для наглядности)

Сначала классы моделей
/**
 * @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;
    }
}


Теперь классы форм - так, как указано в мануале Symfony
// ============= класс формы с общими полями
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,
        ]);
    }
}


С таким кодом вываливается вышепоказанная ошибка. Но я все таки запустил наследование... для этого я изменил классы так:
  • У класса, который ИСПОЛЬЗУЕТ общие поля , я закоментировал добавление их через билдер ->add('commonFields'), и добавил метод getParent()
  • А у класса формы, который СОДЕРЖИТ общие поля - закоментировал строку '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,
        ]);
    }


В итоге все работает. 5c6acefbdc96a920071084.png

Я не понимаю... что я делаю не так? Почему не работает вариант указанный в мануале симфони... Способ которым удалось завести, частично нашел на одном из форумов (увидел что можно добавить метод getParent() - дальше вывалилась новая ошибка, и ее устраняя все завелось.).

Symfony 4.2.0
  • Вопрос задан
  • 226 просмотров
Решения вопроса 1
Matmode
@Matmode
PHP/Symfony Developer
В начальном варианте Вы пытаетесь встроить форму, а не наследовать её. В этом случае поля были бы доступны для вывода так: form.commonFields.titleLink.

Вашу задачу наследования решает именно второй вариант
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы