Doctrine Table 继承与 zf3 字段集
Doctrine Table inheritance with zf3 fieldset
我正在使用 Zend Framework 3 和 Doctrine 2 开发一个项目,用于 DcotrineModule 集成,以下是我遇到问题的实体建模:
为了使用我使用@InheritanceType 的学说进行建模,以下是实体的相关摘录:
Pessoa 实体:
/**
* Abstração de Pessoa
*
* @author Rodrigo Teixeira Andreotti <ro.andriotti@gmail.com>
*
* @Entity
* @InheritanceType("JOINED")
* @DiscriminatorColumn(name="tipo", type="string")
* @DiscriminatorMap( { "pessoa" = "Pessoa",
* "pessoa_fisica" = "PessoaFisica",
* "pessoa_juridica" = "PessoaJuridica" } )
* @Table(name="pessoa")
*/
abstract class Pessoa implements JsonSerializable, PessoaInterface
{
use JsonSerializeTrait;
/**
* @Id
* @GeneratedValue(strategy="IDENTITY")
* @Column(type="integer", length=32, unique=true, nullable=false, name="id_pessoa")
* @var integer
*/
protected $idPessoa;
/**
* Usuário
* @OneToOne(targetEntity="User\Entity\User", inversedBy="pessoa", cascade={"persist"})
* @JoinColumn(name="usuario", referencedColumnName="id")
*
* @var User
*/
protected $usuario;
/**
* @OneToOne(targetEntity="EnderecoPessoa", mappedBy="pessoa", cascade={"persist"})
* @var EnderecoPessoa
*/
protected $endereco;
/**
* Contatos da pessoa
* @OneToMany(targetEntity="ContatoPessoa", mappedBy="pessoa", cascade={"persist"}, orphanRemoval=true)
* @var ArrayCollection|array
*/
protected $contatos;
const PESSOA_FISICA = "pessoa_fisica", PESSOA_JURIDICA = "pessoa_juridica";
public function __construct()
{
$this->contatos = new ArrayCollection();
}
}
PessoaFisica 实体:
/**
* Abstração da pessoa física
*
* @Entity
* @Table(name="pessoa_fisica")
* @author Rodrigo Teixeira Andreotti <ro.andriotti@gmail.com>
*/
class PessoaFisica extends Pessoa implements JsonSerializable {
use JsonSerializeTrait;
/**
* Nome da pessoa física
* @Column(type="string", length=14)
* @var string
*/
private $nome;
/**
* Número do CPF da pessoa (quando brasileiro)
* @Column(type="string", length=14)
* @var string
*/
private $cpf;
/**
* Número do RG (quando brasileiro)
* @Column(type="string", length=13)
* @var string
*/
private $rg;
/**
* Data de nascimento
* @Column(type="date", name="data_nascimento")
* @var DateTime
*/
private $dataNascimento;
}
PessoaJuridica 实体:
/**
* Abstração de Pessoa Jurídica
*
* @Entity
* @Table(name="pessoa_juridica")
* @InheritanceType("JOINED")
* @author Rodrigo Teixeira Andreotti <ro.andriotti@gmail.com>
*/
class PessoaJuridica extends Pessoa implements JsonSerializable {
use JsonSerializeTrait;
/**
* @Id
* @GeneratedValue(strategy="IDENTITY")
* @Column(type="integer", length=32, unique=true, nullable=false, name="id_pessoa")
* @var integer
*/
protected $idPessoa;
/**
* Nome fantasia
* @Column(type="string", length=32, name="nome_fantasia")
* @var String
*/
protected $nomeFantasia;
/**
* Número do CNPJ
* @Column(type="string", length=14, unique=true, name="cnpj")
* @var string
*/
protected $cnpj;
/**
* Razão social da empresa
* @Column(type="string", length=32, name="razao_social")
* @var string Razão social da empresa, quando necessário
*/
protected $razaoSocial;
}
到目前为止一切正常,问题是当我需要为这些信息生成一个表格时,我目前正在研究 "Customer" 模块,基本上我为它所做的是:
- 使用客户端 ID + Pessoa 字段集创建表单
- 在 Pessoa 字段集中,我为共享信息(用户、地址、联系人等)创建了字段集
- 在 Pessoa Fieldset 中,它还包括另外两个 Fieldset,一个用于每个 Pessoa 的 child class(PessoaFisica 和 PessoaJuridica)——问题来了。
在下面的屏幕中你可以看到我的注册表:
此表单使用 javascript 根据所选类型显示或隐藏 PessoaJuridica 或 PessoaFisica 的字段集,但是由于它们在表单中是不同的字段集,因此当 zend 水化它们时,它们被水化为不同的 objects也一样,即继承不适用于Personobject,要根据类型选择。
基本上,在我看来,需要发生的是,zend 有一种方法可以不渲染引用 Person 的 child classes 的字段集class 作为单独的 objects,目前使用这些字段呈现表单,因此(例如):
人 [fsPeople] [姓名]
人 [fsPessoaJuridica] [nameFantasica]
这导致 zend 无法生成正确的 class 保存在数据库中。
执行此表单的正确方法是什么?
好吧,@rkeet 的回复帮助我了解了问题出在哪里,这并不是真正的问题 =]
Due to the usage of inheritance, you've created separate Entities.
However, the form you initially create in the back-end works with a
single Entity. The front-end you've modified to handle 2. So your
front-end does not match your back-end. As, due to the inheritance,
you now have 2 separate Entities, you should create 2 separate forms,
using different fieldsets (PessoaJuridica or PessoaFisica) as the base
fieldsets.
我就把我走过的路留在这里,也许能帮到和我有同样疑惑的人。
首先,按照他评论中解释的逻辑,我为 PessoaEntity 创建了一个抽象字段集,其中包含两类人之间共享的信息,并将其扩展为两个子 classes PessoaFisicaFieldset 和 PessoaJuridicaFieldset,我在下面描述:
/**
* Fieldset com dados para a pessoa
*
* @author Rodrigo Teixeira Andreotti <ro.andriotti@gmail.com>
*/
abstract class PessoaFieldset extends Fieldset implements InputFilterProviderInterface
{
private $em;
private $userFs;
private $enderecoFs;
private $contatoFs;
public function __construct(ObjectManager $em,
UserFieldset $userFs,
PessoaEnderecoFieldset $enderecoFs,
ContatoFieldset $contatoFs)
{
parent::__construct('pessoa');
$this->em = $em;
$this->userFs = $userFs;
$this->enderecoFs = $enderecoFs;
$this->contatoFs = $contatoFs;
$this->init();
}
protected function getEm()
{
return $this->em;
}
public function init()
{
$this
->setHydrator(new DoctrineObject($this->getEm()));
$this->add(array(
'type' => 'Hidden',
'name' => 'id_pessoa',
'attributes' => array(
'id' => 'txtId'
)
));
$this->add(array(
'type' => 'hidden',
'name' => 'tipo',
));
$this->add($this->userFs);
$this->add($this->enderecoFs);
$elCollection = new Collection;
$elCollection
->setName('contatos')
->setLabel('Informações de Contato')
->setCount(1)
->setShouldCreateTemplate(true)
->setAllowAdd(true)
->setAllowRemove(true)
->setTargetElement($this->contatoFs);
$this->add($elCollection);
$this->add(array(
'type' => 'Button',
'name' => 'btAddContato',
'options' => array(
'label' => '<i class="fa fa-fw fa-plus"></i> Adicionar',
'label_options' => array(
'disable_html_escape' => true
)
),
'attributes' => array(
'class' => 'btn btn-info',
'id' => 'btAddContato'
)
));
}
public function getInputFilterSpecification(): array
{
return array(
'id_pessoa' => array(
'required' => false,
'filters' => array(
['name'=>'Int']
)
),
'tipo' => array(
'required' => true,
)
);
}
}
这是我的 PessoaFisicaFieldset class。
/**
* Fieldset com dados para a pessoa Física
*
* @author Rodrigo Teixeira Andreotti <ro.andriotti@gmail.com>
*/
class PessoaFisicaFieldset extends PessoaFieldset implements InputFilterProviderInterface
{
private $em;
public function __construct(ObjectManager $em,
\User\Form\UserFieldset $userFs,
PessoaEnderecoFieldset $enderecoFs,
\Common\Form\ContatoFieldset $contatoFs)
{
parent::__construct($em, $userFs, $enderecoFs, $contatoFs);
$this->init();
}
public function init()
{
parent::init();
$this
->setObject(new PessoaFisica());
$this->get('tipo')->setValue(\Pessoa\Entity\Pessoa::PESSOA_FISICA);
$this->add(array(
'type' => 'Text',
'name' => 'cpf',
'options' => array(
'label' => 'CPF',
'label_attributes' => array(
'class' => 'col-sm-12'
)
),
'attributes' => array(
'class' => 'form-control form-control-line',
'id' => 'txtCpf'
)
));
$this->add(array(
'type' => 'Text',
'name' => 'nome',
'options' => array(
'label' => 'Nome',
'label_attributes' => array(
'class' => 'col-sm-12'
)
),
'attributes' => array(
'class' => 'form-control form-control-line',
'id' => 'txtNome'
)
));
$this->add(array(
'type' => 'Text',
'name' => 'rg',
'options' => array(
'label' => 'RG',
'label_attributes' => array(
'class' => 'col-sm-12'
)
),
'attributes' => array(
'class' => 'form-control form-control-line',
'id' => 'txtRazaoSocial'
)
));
$this->add(array(
'type' => 'DateTime',
'name' => 'dataNascimento',
'options' => array(
'format' => 'd/m/Y',
'label' => 'Data de Nascimento',
'label_attributes' => array(
'class' => 'col-sm-12'
)
),
'attributes' => array(
'class' => 'form-control form-control-line data',
)
));
}
public function getInputFilterSpecification(): array
{
return array(
'nome' => array(
'required' => true,
'filters' => array(
['name' => 'StripTags'],
['name' => 'StringTrim']
)
),
'rg' => array(
'required' => false,
'filters' => array(
['name' => 'StripTags'],
['name' => 'StringTrim']
)
),
'cpf' => array(
'required' => false,
'filters' => array(
['name' => 'StripTags'],
['name' => 'StringTrim']
),
'validators' => array(
['name' => CpfValidator::class]
)
),
'dataNascimento' => array(
'required' => true,
'filters' => array(
array(
'name' => 'Zend\Filter\DatetimeFormatter',
'options' => array (
'format' => 'd/m/Y',
),
),
),
'validators' => array(
array(
'name' => Date::class,
'options' => array(
'format' => 'd/m/Y'
)
)
)
)
);
}
}
这是我的 PessoaJuridicaFieldset
/**
* Fieldset com dados específicos para a pessoa jurídica
*
* @author Rodrigo Teixeira Andreotti <ro.andriotti@gmail.com>
*/
class PessoaJuridicaFieldset extends PessoaFieldset implements InputFilterProviderInterface
{
public function __construct(ObjectManager $em,
\User\Form\UserFieldset $userFs, PessoaEnderecoFieldset $enderecoFs,
\Common\Form\ContatoFieldset $contatoFs)
{
parent::__construct($em, $userFs, $enderecoFs, $contatoFs);
$this->init();
}
public function init()
{
parent::init();
$this
->setObject(new PessoaJuridica());
$this->get('tipo')->setValue(\Pessoa\Entity\Pessoa::PESSOA_JURIDICA);
$this->add(array(
'type' => 'Text',
'name' => 'cnpj',
'options' => array(
'label' => 'CNPJ',
'label_attributes' => array(
'class' => 'col-sm-12'
)
),
'attributes' => array(
'class' => 'form-control form-control-line',
'id' => 'txtCnpj'
)
));
$this->add(array(
'type' => 'Text',
'name' => 'razaoSocial',
'options' => array(
'label' => 'Razão Social',
'label_attributes' => array(
'class' => 'col-sm-12'
)
),
'attributes' => array(
'class' => 'form-control form-control-line',
'id' => 'txtRazaoSocial'
)
));
$this->add(array(
'type' => 'Text',
'name' => 'nomeFantasia',
'options' => array(
'label' => 'Nome Fantasia',
'label_attributes' => array(
'class' => 'col-sm-12'
)
),
'attributes' => array(
'class' => 'form-control form-control-line',
'id' => 'txtNomeFantasia'
)
));
}
public function getInputFilterSpecification(): array
{
return array(
'razaoSocial' => array(
'required' => true,
'filters' => array(
['name' => 'StripTags'],
['name' => 'StringTrim']
)
),
'nomeFantasia' => array(
'required' => true,
'filters' => array(
['name' => 'StripTags'],
['name' => 'StringTrim']
)
),
'cnpj' => array(
'required' => true,
'filters' => array(
['name' => 'StripTags'],
['name' => 'StringTrim']
),
'validators' => array(
['name' => CnpjValidator::class]
)
)
);
}
}
为了完成,我在将加载此表单的控制器上进行了实体类型处理,如下所示:(仅相关部分)
//...
if ($id) {
$cliente = $this->repository->getById($id);
$form->remove('pessoa');
// loads form according to the type loaded from the database
if (!$request->isXmlHttpRequest()) {
if ($cliente->getPessoa() instanceof \Pessoa\Entity\PessoaFisica) {
$form->add($this->pessoaFisicaFieldset);
} elseif ($cliente->getPessoa() instanceof \Pessoa\Entity\PessoaJuridica) {
$form->add($this->pessoaJuridicaFieldset);
}
var_dump($cliente->getPessoa());
}
$form->bind($cliente);
}
if ($request->isPost()) {
$form->remove('pessoa');
// loads form according to the type selected in the post
if ($request->getPost('tipo') == \Pessoa\Entity\Pessoa::PESSOA_FISICA) {
$form->add($this->pessoaFisicaFieldset);
} elseif ($request->getPost('tipo') == \Pessoa\Entity\Pessoa::PESSOA_JURIDICA) {
$form->add($this->pessoaJuridicaFieldset);
}
$form->get('tipo')->setValue($request->getPost('tipo'));
$form->setData($request->getPost());
if(!$request->isXmlHttpRequest()) {
if ($form->isValid()) {
$cliente = $form->getObject();
if ($cliente->getId() != 0) {
$cliente->getPessoa()->setCadastradoEm(new \DateTime);
}
// ...
}
}
}
//...
再次感谢@rkeet!
我正在使用 Zend Framework 3 和 Doctrine 2 开发一个项目,用于 DcotrineModule 集成,以下是我遇到问题的实体建模:
为了使用我使用@InheritanceType 的学说进行建模,以下是实体的相关摘录:
Pessoa 实体:
/**
* Abstração de Pessoa
*
* @author Rodrigo Teixeira Andreotti <ro.andriotti@gmail.com>
*
* @Entity
* @InheritanceType("JOINED")
* @DiscriminatorColumn(name="tipo", type="string")
* @DiscriminatorMap( { "pessoa" = "Pessoa",
* "pessoa_fisica" = "PessoaFisica",
* "pessoa_juridica" = "PessoaJuridica" } )
* @Table(name="pessoa")
*/
abstract class Pessoa implements JsonSerializable, PessoaInterface
{
use JsonSerializeTrait;
/**
* @Id
* @GeneratedValue(strategy="IDENTITY")
* @Column(type="integer", length=32, unique=true, nullable=false, name="id_pessoa")
* @var integer
*/
protected $idPessoa;
/**
* Usuário
* @OneToOne(targetEntity="User\Entity\User", inversedBy="pessoa", cascade={"persist"})
* @JoinColumn(name="usuario", referencedColumnName="id")
*
* @var User
*/
protected $usuario;
/**
* @OneToOne(targetEntity="EnderecoPessoa", mappedBy="pessoa", cascade={"persist"})
* @var EnderecoPessoa
*/
protected $endereco;
/**
* Contatos da pessoa
* @OneToMany(targetEntity="ContatoPessoa", mappedBy="pessoa", cascade={"persist"}, orphanRemoval=true)
* @var ArrayCollection|array
*/
protected $contatos;
const PESSOA_FISICA = "pessoa_fisica", PESSOA_JURIDICA = "pessoa_juridica";
public function __construct()
{
$this->contatos = new ArrayCollection();
}
}
PessoaFisica 实体:
/**
* Abstração da pessoa física
*
* @Entity
* @Table(name="pessoa_fisica")
* @author Rodrigo Teixeira Andreotti <ro.andriotti@gmail.com>
*/
class PessoaFisica extends Pessoa implements JsonSerializable {
use JsonSerializeTrait;
/**
* Nome da pessoa física
* @Column(type="string", length=14)
* @var string
*/
private $nome;
/**
* Número do CPF da pessoa (quando brasileiro)
* @Column(type="string", length=14)
* @var string
*/
private $cpf;
/**
* Número do RG (quando brasileiro)
* @Column(type="string", length=13)
* @var string
*/
private $rg;
/**
* Data de nascimento
* @Column(type="date", name="data_nascimento")
* @var DateTime
*/
private $dataNascimento;
}
PessoaJuridica 实体:
/**
* Abstração de Pessoa Jurídica
*
* @Entity
* @Table(name="pessoa_juridica")
* @InheritanceType("JOINED")
* @author Rodrigo Teixeira Andreotti <ro.andriotti@gmail.com>
*/
class PessoaJuridica extends Pessoa implements JsonSerializable {
use JsonSerializeTrait;
/**
* @Id
* @GeneratedValue(strategy="IDENTITY")
* @Column(type="integer", length=32, unique=true, nullable=false, name="id_pessoa")
* @var integer
*/
protected $idPessoa;
/**
* Nome fantasia
* @Column(type="string", length=32, name="nome_fantasia")
* @var String
*/
protected $nomeFantasia;
/**
* Número do CNPJ
* @Column(type="string", length=14, unique=true, name="cnpj")
* @var string
*/
protected $cnpj;
/**
* Razão social da empresa
* @Column(type="string", length=32, name="razao_social")
* @var string Razão social da empresa, quando necessário
*/
protected $razaoSocial;
}
到目前为止一切正常,问题是当我需要为这些信息生成一个表格时,我目前正在研究 "Customer" 模块,基本上我为它所做的是:
- 使用客户端 ID + Pessoa 字段集创建表单
- 在 Pessoa 字段集中,我为共享信息(用户、地址、联系人等)创建了字段集
- 在 Pessoa Fieldset 中,它还包括另外两个 Fieldset,一个用于每个 Pessoa 的 child class(PessoaFisica 和 PessoaJuridica)——问题来了。
在下面的屏幕中你可以看到我的注册表:
此表单使用 javascript 根据所选类型显示或隐藏 PessoaJuridica 或 PessoaFisica 的字段集,但是由于它们在表单中是不同的字段集,因此当 zend 水化它们时,它们被水化为不同的 objects也一样,即继承不适用于Personobject,要根据类型选择。
基本上,在我看来,需要发生的是,zend 有一种方法可以不渲染引用 Person 的 child classes 的字段集class 作为单独的 objects,目前使用这些字段呈现表单,因此(例如):
人 [fsPeople] [姓名]
人 [fsPessoaJuridica] [nameFantasica]
这导致 zend 无法生成正确的 class 保存在数据库中。
执行此表单的正确方法是什么?
好吧,@rkeet 的回复帮助我了解了问题出在哪里,这并不是真正的问题 =]
Due to the usage of inheritance, you've created separate Entities. However, the form you initially create in the back-end works with a single Entity. The front-end you've modified to handle 2. So your front-end does not match your back-end. As, due to the inheritance, you now have 2 separate Entities, you should create 2 separate forms, using different fieldsets (PessoaJuridica or PessoaFisica) as the base fieldsets.
我就把我走过的路留在这里,也许能帮到和我有同样疑惑的人。
首先,按照他评论中解释的逻辑,我为 PessoaEntity 创建了一个抽象字段集,其中包含两类人之间共享的信息,并将其扩展为两个子 classes PessoaFisicaFieldset 和 PessoaJuridicaFieldset,我在下面描述:
/**
* Fieldset com dados para a pessoa
*
* @author Rodrigo Teixeira Andreotti <ro.andriotti@gmail.com>
*/
abstract class PessoaFieldset extends Fieldset implements InputFilterProviderInterface
{
private $em;
private $userFs;
private $enderecoFs;
private $contatoFs;
public function __construct(ObjectManager $em,
UserFieldset $userFs,
PessoaEnderecoFieldset $enderecoFs,
ContatoFieldset $contatoFs)
{
parent::__construct('pessoa');
$this->em = $em;
$this->userFs = $userFs;
$this->enderecoFs = $enderecoFs;
$this->contatoFs = $contatoFs;
$this->init();
}
protected function getEm()
{
return $this->em;
}
public function init()
{
$this
->setHydrator(new DoctrineObject($this->getEm()));
$this->add(array(
'type' => 'Hidden',
'name' => 'id_pessoa',
'attributes' => array(
'id' => 'txtId'
)
));
$this->add(array(
'type' => 'hidden',
'name' => 'tipo',
));
$this->add($this->userFs);
$this->add($this->enderecoFs);
$elCollection = new Collection;
$elCollection
->setName('contatos')
->setLabel('Informações de Contato')
->setCount(1)
->setShouldCreateTemplate(true)
->setAllowAdd(true)
->setAllowRemove(true)
->setTargetElement($this->contatoFs);
$this->add($elCollection);
$this->add(array(
'type' => 'Button',
'name' => 'btAddContato',
'options' => array(
'label' => '<i class="fa fa-fw fa-plus"></i> Adicionar',
'label_options' => array(
'disable_html_escape' => true
)
),
'attributes' => array(
'class' => 'btn btn-info',
'id' => 'btAddContato'
)
));
}
public function getInputFilterSpecification(): array
{
return array(
'id_pessoa' => array(
'required' => false,
'filters' => array(
['name'=>'Int']
)
),
'tipo' => array(
'required' => true,
)
);
}
}
这是我的 PessoaFisicaFieldset class。
/**
* Fieldset com dados para a pessoa Física
*
* @author Rodrigo Teixeira Andreotti <ro.andriotti@gmail.com>
*/
class PessoaFisicaFieldset extends PessoaFieldset implements InputFilterProviderInterface
{
private $em;
public function __construct(ObjectManager $em,
\User\Form\UserFieldset $userFs,
PessoaEnderecoFieldset $enderecoFs,
\Common\Form\ContatoFieldset $contatoFs)
{
parent::__construct($em, $userFs, $enderecoFs, $contatoFs);
$this->init();
}
public function init()
{
parent::init();
$this
->setObject(new PessoaFisica());
$this->get('tipo')->setValue(\Pessoa\Entity\Pessoa::PESSOA_FISICA);
$this->add(array(
'type' => 'Text',
'name' => 'cpf',
'options' => array(
'label' => 'CPF',
'label_attributes' => array(
'class' => 'col-sm-12'
)
),
'attributes' => array(
'class' => 'form-control form-control-line',
'id' => 'txtCpf'
)
));
$this->add(array(
'type' => 'Text',
'name' => 'nome',
'options' => array(
'label' => 'Nome',
'label_attributes' => array(
'class' => 'col-sm-12'
)
),
'attributes' => array(
'class' => 'form-control form-control-line',
'id' => 'txtNome'
)
));
$this->add(array(
'type' => 'Text',
'name' => 'rg',
'options' => array(
'label' => 'RG',
'label_attributes' => array(
'class' => 'col-sm-12'
)
),
'attributes' => array(
'class' => 'form-control form-control-line',
'id' => 'txtRazaoSocial'
)
));
$this->add(array(
'type' => 'DateTime',
'name' => 'dataNascimento',
'options' => array(
'format' => 'd/m/Y',
'label' => 'Data de Nascimento',
'label_attributes' => array(
'class' => 'col-sm-12'
)
),
'attributes' => array(
'class' => 'form-control form-control-line data',
)
));
}
public function getInputFilterSpecification(): array
{
return array(
'nome' => array(
'required' => true,
'filters' => array(
['name' => 'StripTags'],
['name' => 'StringTrim']
)
),
'rg' => array(
'required' => false,
'filters' => array(
['name' => 'StripTags'],
['name' => 'StringTrim']
)
),
'cpf' => array(
'required' => false,
'filters' => array(
['name' => 'StripTags'],
['name' => 'StringTrim']
),
'validators' => array(
['name' => CpfValidator::class]
)
),
'dataNascimento' => array(
'required' => true,
'filters' => array(
array(
'name' => 'Zend\Filter\DatetimeFormatter',
'options' => array (
'format' => 'd/m/Y',
),
),
),
'validators' => array(
array(
'name' => Date::class,
'options' => array(
'format' => 'd/m/Y'
)
)
)
)
);
}
}
这是我的 PessoaJuridicaFieldset
/**
* Fieldset com dados específicos para a pessoa jurídica
*
* @author Rodrigo Teixeira Andreotti <ro.andriotti@gmail.com>
*/
class PessoaJuridicaFieldset extends PessoaFieldset implements InputFilterProviderInterface
{
public function __construct(ObjectManager $em,
\User\Form\UserFieldset $userFs, PessoaEnderecoFieldset $enderecoFs,
\Common\Form\ContatoFieldset $contatoFs)
{
parent::__construct($em, $userFs, $enderecoFs, $contatoFs);
$this->init();
}
public function init()
{
parent::init();
$this
->setObject(new PessoaJuridica());
$this->get('tipo')->setValue(\Pessoa\Entity\Pessoa::PESSOA_JURIDICA);
$this->add(array(
'type' => 'Text',
'name' => 'cnpj',
'options' => array(
'label' => 'CNPJ',
'label_attributes' => array(
'class' => 'col-sm-12'
)
),
'attributes' => array(
'class' => 'form-control form-control-line',
'id' => 'txtCnpj'
)
));
$this->add(array(
'type' => 'Text',
'name' => 'razaoSocial',
'options' => array(
'label' => 'Razão Social',
'label_attributes' => array(
'class' => 'col-sm-12'
)
),
'attributes' => array(
'class' => 'form-control form-control-line',
'id' => 'txtRazaoSocial'
)
));
$this->add(array(
'type' => 'Text',
'name' => 'nomeFantasia',
'options' => array(
'label' => 'Nome Fantasia',
'label_attributes' => array(
'class' => 'col-sm-12'
)
),
'attributes' => array(
'class' => 'form-control form-control-line',
'id' => 'txtNomeFantasia'
)
));
}
public function getInputFilterSpecification(): array
{
return array(
'razaoSocial' => array(
'required' => true,
'filters' => array(
['name' => 'StripTags'],
['name' => 'StringTrim']
)
),
'nomeFantasia' => array(
'required' => true,
'filters' => array(
['name' => 'StripTags'],
['name' => 'StringTrim']
)
),
'cnpj' => array(
'required' => true,
'filters' => array(
['name' => 'StripTags'],
['name' => 'StringTrim']
),
'validators' => array(
['name' => CnpjValidator::class]
)
)
);
}
}
为了完成,我在将加载此表单的控制器上进行了实体类型处理,如下所示:(仅相关部分)
//...
if ($id) {
$cliente = $this->repository->getById($id);
$form->remove('pessoa');
// loads form according to the type loaded from the database
if (!$request->isXmlHttpRequest()) {
if ($cliente->getPessoa() instanceof \Pessoa\Entity\PessoaFisica) {
$form->add($this->pessoaFisicaFieldset);
} elseif ($cliente->getPessoa() instanceof \Pessoa\Entity\PessoaJuridica) {
$form->add($this->pessoaJuridicaFieldset);
}
var_dump($cliente->getPessoa());
}
$form->bind($cliente);
}
if ($request->isPost()) {
$form->remove('pessoa');
// loads form according to the type selected in the post
if ($request->getPost('tipo') == \Pessoa\Entity\Pessoa::PESSOA_FISICA) {
$form->add($this->pessoaFisicaFieldset);
} elseif ($request->getPost('tipo') == \Pessoa\Entity\Pessoa::PESSOA_JURIDICA) {
$form->add($this->pessoaJuridicaFieldset);
}
$form->get('tipo')->setValue($request->getPost('tipo'));
$form->setData($request->getPost());
if(!$request->isXmlHttpRequest()) {
if ($form->isValid()) {
$cliente = $form->getObject();
if ($cliente->getId() != 0) {
$cliente->getPessoa()->setCadastradoEm(new \DateTime);
}
// ...
}
}
}
//...
再次感谢@rkeet!