表单继承问题


Issues with form inheritance

我有一个PersonType表单,然后有LegalPersonTypeNaturalPersonType表单,它们都是从PersonType扩展而来的,因为它们在该表单上有一个公共字段(在实体级别映射)。例如,这是NaturalPersonType.php 的代码

use Symfony'Component'Form'FormBuilderInterface;
use Symfony'Component'OptionsResolver'OptionsResolverInterface;
use Tanane'FrontendBundle'DBAL'Types'CIType;
use Tanane'FrontendBundle'Form'Type'PersonType;
class NaturalPersonType extends PersonType {
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        parent::buildForm($builder, $options);
        $builder
                ->add('identification_type', 'choice', array(
                    'label' => 'Número de Cédula',
                    'choices' => CIType::getChoices()
                ))
                ->add('ci', 'number', array(
                    'required' => true,
                    'label' => false,
                    'attr' => array(
                        'maxlength' => 8,
                    ))
                )
                ->add('lives_in_ccs', 'checkbox', array(
                    'label' => false,
                    'required' => false,
                    'value' => 1,
        ));
    }
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Tanane'FrontendBundle'Entity'NaturalPerson'
        ));
    }
    public function getName()
    {
        return 'natural_person';
    }
}

然后在SaveFormController/orderAction()中,我将执行以下操作:

$order = new Orders();
$orderForm = $this->createForm(new OrdersType(array($type)), $order, array('action' => $this->generateUrl('save_order')));

但每当我试图呈现表单时,我都会遇到以下错误:

属性"nat"和方法"getNat()"、"nat(),类中存在"isNat()"、"hasNat(()"answers"__get()"并具有公共访问权限"Tanane''FrontendBundle''Entity''Orders"。

关系处于实体级别,我如何修复该错误?

提前感谢

第一个可能的解决方案

根据用户的建议,我在OrderType.php中将我的代码改为:

use Symfony'Component'Form'AbstractType;
use Symfony'Component'Form'FormBuilderInterface;
use Symfony'Component'OptionsResolver'OptionsResolverInterface;
use Tanane'FrontendBundle'DBAL'Types'SFType;
class OrdersType extends AbstractType {
    /**
     * @var string
     */
    protected $register_type;
    public function __construct($register_type)
    {
        $this->register_type = $register_type;
    }
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        // here goes $builder with default options remove for see less code
        if ($this->register_type[0] == "natural")
        {
            $builder->add('nat', new NaturalPersonType(), array(
                'data_class' => 'Tanane'FrontendBundle'Entity'NaturalPerson'
            ));
        }
        elseif ($this->register_type[0] == "legal")
        {
            $builder->add('leg', new LegalPersonType(), array(
                'data_class' => 'Tanane'FrontendBundle'Entity'LegalPerson'
            ));
        }
    }
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Tanane'FrontendBundle'Entity'Orders',
            'render_fieldset' => FALSE,
            'show_legend' => FALSE
        ));
    }
    public function getName()
    {
        return 'orders';
    }
}

我已经修复了在OrdersType中添加的每个新FormType上添加'mapped' => FALSE的问题,但我不知道这是否正确。此外,如果我在这里定义data_class,并且NaturalType永远不会直接通过OrdersType访问,我应该从该表单中删除默认选项,还是应该将它们留在那里?我现在该如何解决这个问题?我缺少什么?

这不是你问题的直接答案,但可能会在问题发生之前解决一些问题。。。

我不记得见过可以扩展这样的表单,而不是扩展AbstractType,但正如文档中所解释的,如果您在不同类型的表单之间有共享的公共字段,则应该使用inherit_data提供的本地框架模块化。

如果您需要更具体的东西(在某个字段上执行一些特殊的方法),您可以使用AbstractTypeExtension创建一个新的字段类型或扩展现有的字段类型。

编辑

我不知道你为什么使用这种方法(我从未在我的项目中使用过),但IMO PersonTypeNaturalPersonTypeLegalPersonType应该只是用inherit_data初始化的"FormType/FieldType"(而不是像你的代码中那样的实体),其中包含与它们的使用相关的字段,而OrdersType应该由填写者类型所需的表格块和在存储表格输出数据的UNIQUE实体上设置的data_class组成。