我正在使用Zend Framework 3和Doctrine 2进行项目开发,并用于DcotrineModule集成,以下是我遇到问题的实体建模:
要使用我使用@InheritanceType的学说来进行此建模,以下是实体的相关摘录:
佩索阿实体:
/**
* 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;
}
到目前为止,一切都运行良好,问题是当我需要为该信息生成表单时,我目前正在使用“客户”模块,基本上我所做的是:
此表单根据使用javascript的选定类型显示或隐藏PessoaJuridica或PessoaFisica的字段集,但是由于它们是表单中的不同字段集,因此zend将它们水合时,它们也被水合为不同的对象,即,继承不是应用于Person对象,应根据类型进行选择。
从我的角度来看,基本上需要发生的事情是,有一种zend的方法,在表单为当前形式时,它不会将引用Person类的子类的字段集呈现为单独的对象使用这些字段进行渲染(例如):
人[fsPeople] [姓名]
人[fsPessoaJuridica] [nameFantasica]
这会导致zend无法生成要保存在数据库中的正确类。
执行表单的正确方法是什么?
答案 0 :(得分:0)
好吧,@ rkeet的回复帮助我了解了问题出在哪里,这实际上不是问题=]
由于继承的使用,您创建了单独的实体。 但是,您最初在后端创建的表单可以使用 单一实体。您已修改以处理2的前端。 前端与您的后端不匹配。因为,由于继承, 您现在有2个独立的实体,应该创建2个独立的表单, 使用不同的字段集(PessoaJuridica或PessoaFisica)作为基础 字段集。
我将离开我遵循的道路,这可能会帮助和我一样有疑问的人。
首先,按照他的评论中解释的逻辑,我为PessoaEntity创建了一个抽象字段集,其中包含了两种类型的人之间共享的信息,并将其扩展为两个子类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类。
/**
* 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]
)
)
);
}
}
最后,我在Controller上进行了实体类型处理,将加载此表单,如下所示:(仅相关部分)
//...
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!