在实体之间共享FormType,最佳实践/方法

时间:2014-10-16 01:50:12

标签: php symfony symfony-forms

我有一些共享相同结构的实体,例如,将这两个作为基本示例:

/**
 * @ORM\Entity
 * @ORM\Table(name="nomencladores.modelo", schema="nomencladores")
 */
class Modelo
{
    use IdentifierAutogeneratedEntityTrait;
    use NamedEntityTrait;
    use ActiveEntityTrait;

    /**
     * @var \TipoTramite
     *
     * @ORM\ManyToOne(targetEntity="TipoTramite")
     * @ORM\JoinColumn(name="tipo_tramite_id", referencedColumnName="id")
     */
    protected $tipo_tramite;

    /**
     * Set tipo tramite
     *
     * @param  \ComunBundle\Entity\TipoTramite $tipo_tramite
     * @return FabricanteDistribuidor
     */
    public function setTipoTramite(\ComunBundle\Entity\TipoTramite $tipo_tramite)
    {
        $this->tipo_tramite = $tipo_tramite;

        return $this;
    }

    /**
     * Get tipo tramite
     *
     * @return \ComunBundle\Entity\TipoTramite
     */
    public function getTipoTramite()
    {
        return $this->tipo_tramite;
    }

}

/**
 * @ORM\Entity
 * @ORM\Table(name="nomencladores.marca", schema="nomencladores")
 */
class Marca
{
    use IdentifierAutogeneratedEntityTrait;
    use NamedEntityTrait;
    use ActiveEntityTrait;

    /**
     * @var \TipoTramite
     *
     * @ORM\ManyToOne(targetEntity="TipoTramite")
     * @ORM\JoinColumn(name="tipo_tramite_id", referencedColumnName="id")
     */
    protected $tipo_tramite;

    /**
     * Set tipo tramite
     *
     * @param  \ComunBundle\Entity\TipoTramite $tipo_tramite
     * @return FabricanteDistribuidor
     */
    public function setTipoTramite(\ComunBundle\Entity\TipoTramite $tipo_tramite)
    {
        $this->tipo_tramite = $tipo_tramite;

        return $this;
    }

    /**
     * Get tipo tramite
     *
     * @return \ComunBundle\Entity\TipoTramite
     */
    public function getTipoTramite()
    {
        return $this->tipo_tramite;
    }

}

正如您在上面的代码中看到的,实体共享几乎相同的代码,只需更改存储信息的表。现在我需要为每个表单构建一个表单,并且基本上会有一些小的更改,请参阅Modelo实体的示例:

class ModeloType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
                ->add('nombre')
                ->add('activo')
                ->add('tipo_tramite', 'entity', array(
                    'class' => 'ComunBundle:TipoTramite',
                    'property' => 'nombre',
                    'empty_value' => '-- SELECCIONAR --',
                    'query_builder' => function (EntityRepository $er) {
                        return $er->createQueryBuilder('qb')
                                ->where('qb.activo = :activoValue')
                                ->setParameter('activoValue', TRUE);
                    }
        ));
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'ComunBundle\Entity\Modelo'
        ));
    }

    public function getName()
    {
        return 'Modelo';
    }

}

因此,在一个FormType和另一个FormType之间唯一的变化是:类名,data_class属性和getName()返回值,有没有办法在FormType上应用DRY方案

1 个答案:

答案 0 :(得分:1)

首先,拥有两个几乎相同的实体(因此两个几乎相同的表)对我来说似乎是一种气味 - 我很难想到以某种方式将它们组合成一个实体以及一些额外的类别来区分它们。

除此之外,您是否可以定义自己的中间抽象类型,然后继承更改那两个不同的小东西,例如:

//This is not a good name, I'm sure you can do better!
abstract class AbstractModeloMarcaType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
                ->add('nombre')
                ->add('activo')
                ->add('tipo_tramite', 'entity', array(
                    'class' => 'ComunBundle:TipoTramite',
                    'property' => 'nombre',
                    'empty_value' => '-- SELECCIONAR --',
                    'query_builder' => function (EntityRepository $er) {
                        return $er->createQueryBuilder('qb')
                                ->where('qb.activo = :activoValue')
                                ->setParameter('activoValue', TRUE);
                    }
        ));
    }

    abstract protected function getDataClass();

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => $this->getDataClass()
        ));
    }

}

public class ModeloType extends AbstractModeloMarcaType 
{
    public function getName()
    {
        return 'Modelo';
    }

    public function getDataClass()
    {
        return 'ComunBundle\Entity\Modelo';
    }
}

public class MarcaType extends AbstractModeloMarcaType 
{
    public function getName()
    {
        return 'Marca';
    }

    public function getDataClass()
    {
        return 'ComunBundle\Entity\Marca';
    }
}