У меня есть некоторые объекты, которые имеют одинаковую структуру, например, взять эти два в качестве базового примера:
/**
* @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 и другим, будет: имя класса, data_class
атрибут и getName()
Возвращаемое значение, есть ли способ применить DRY к FormType в этом сценарии?
Во-первых, наличие двух почти идентичных сущностей (и, следовательно, двух почти идентичных таблиц) кажется мне запахом — я бы подумал о том, чтобы как-то объединить их в одну сущность с какой-то дополнительной категорией, чтобы различать их.
Помимо этого, вы можете просто определить свой собственный промежуточный абстрактный тип, а затем унаследовать от этого изменения тех двух небольших вещей, которые отличаются, например,
//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';
}
}
Других решений пока нет …