表单继承的问题

时间:2014-09-03 02:14:54

标签: php symfony inheritance symfony-forms

我有一个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()"," __ get()"在课堂上存在并具有公共访问权限   "塔南\ FrontendBundle \实体\订单"

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

提前致谢

第一种可能的解决方案

根据用户的建议,我在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';
    }

}

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

1 个答案:

答案 0 :(得分:1)

这不是你问题的直接答案,但可能在此之前解决一些问题......

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

如果您需要更具体的内容(在某些字段上执行某些特殊方法),您可以使用AbstractTypeExtension create a new field typeextend an existing one

修改

我不确切知道您使用此方法的原因(我从未在我的项目中使用过),但IMO PersonTypeNaturalPersonTypeLegalPersonType应仅为“FormType / FieldType “使用inherit_data初始化(而不是代码中的实体),其中包含与其使用相关的字段,而OrdersType应该与填充它的人类型所需的表单块组成。在{UNIQUE实体上设置data_class,该实体存储表单输出的数据。