Usando o Engine.DB – Parte 4
Demorou um pouco, mas tá ae: A parte 4 do tutorial do engine.DB. Dando continuidade a nossa seção de tutoriais vamos aprender como o engine.DB trabalha com coleções de objetos. O engine.DB utiliza um objeto chamado Collection para armazenar o array contendo os objetos referenciados no relacionamento. Mas o Collection, além disso, armazena informações sobre as operações realizadas na coleção, otimizando o processo de persistância.
Suponhamos que PessoaFisica agora possua uma coleção de telefones (OneToMany nesse caso).
Nossas entidades consistirão na nossa classe PessoaFisica (modificada para comportar a coleção de telefones), na classe Cliente (ligeiramente modificada do nosso tutorial anterior), na interface IPessoaFisica e no objeto Telefone.

[Importante]
- A classe deve ser criada com acessors (getters/setters) definidos.
- Atenção a forma como os comentários são feitos. Para que o PHP reconheça um comentário como PHPDocComment ele deve necessáriamente começar com /** e terminar com */, caso contrário o Engine.DB nao terá acesso as Annotations contidas nele.
- A classe Cliente , por ser independente nessa modelagem, POSSUI a propriedade ID.
- Atualmente o engine exige que a opção OID esteja setada como true nas tabelas do PostgreSQL.
Definindo o relacionamento entra as entidades (1 pra N) colocamos uma annotation no metodo getTelefones (por padrão, assim como no hibernate, é solicitado que se coloque as annotations de relacionamento nos getters) como especificado:
/** * @OneToMany(mappedBy="pessoa",targetEntity="Telefone",fetch=FetchType.FETCH,cascade=CascadeType.ALL) */
A propriedade mappedBy define qual a propriedade que mapeia a entidade referenciadora [PessoaFisica] na entidade referenciada detentora da FK [Telefone].
A propriedade targetEntity define a classe da entidade mapeada pois o tipo de uma coleção deverá ser obrigatóriamente Collection.
A propriedade fetch determina se o Engine.DB deverá (FetchType.FETCH) ou não (FetchType.LAZY) trazer os dados da entidade do relacionamento.
A propriedade cascade determina se o Engine.DB deverá propagar as operações de criação e atualização (CascadeType.SAVE), somente na criação (CascadeType.CREATE), somente na atualização (CascadeType.UPDATE), somente na exclusão (CascadeType.DELETE) ou nao propagar (CascadeType.NONE) à entidade do relacionamento.
Na nossa classe Telefone anotamos o método getPessoa com:
/** * @ManyToOne */
O código:
<?PHP
<?php
/**
* Engine PHP Application Framework
* http://seelaz.com.br
* File: PessoaFisica.php
**/
/**
* @author Silas R. N. Junior
*/
class PessoaFisica {
/**
* Observe que o nome da classe devera ser identico ao da tabela ou entao
* será preciso definir o nome da tabela com @Table(name="<nome_da_tabela>")
* O mesmo se aplica aos nomes das colunas que utilizam a anotacao @Column(name="<nome_da_coluna>")
* A definição do tipo da propriedade utilizando @var é levada em consideração pelo Engine. Se omitido
* será considerado o tipo string.
*/
/**
* @var int
* @Id - define como chave primaria esta propriedade
*/
private $id;
/**
* @var string
*/
private $rg;
/**
* @var Collection
*/
private $telefones;
/**
* @return int
*/
public function getId() {
return $this->id;
}
/**
* @param int $newId
* @return void
*/
public function setId($newId) {
$this->id = $newId;
}
/**
* @return string
*/
public function getRg() {
return $this->rg;
}
/**
* @param string $newRg
* @return void
*/
public function setRg($newRg) {
$this->rg = $newRg;
}
/**
* @OneToMany(mappedBy="pessoa",targetEntity="Telefone",fetch=FetchType.FETCH,cascade=CascadeType.ALL)
* @return Collection
*/
public function getTelefones() {
return $this->telefones;
}
/**
* @param Collection $newTelefones
* @return void
*/
public function setTelefones(Collection $newTelefones) {
$this->telefones = $newTelefones;
}
}
/**
* Engine PHP Application Framework
* http://seelaz.com.br
* File: Cliente.php
**/
/**
* @author Silas R. N. Junior
*/
class Cliente implements IPessoaFisica {
/**
* @var int
*/
private $id;
/**
* @var int
*/
private $codigo;
/**
* @var PessoaFisica
*/
private $pF;
/**
* @Id
* @return int
*/
public function getId() {
return $this->id;
}
/**
* @param int $newId
* @return void
*/
public function setId($newId) {
$this->id = $newId;
}
/**
* @return int
*/
public function getCodigo() {
return $this->codigo;
}
/**
* @param int $newCodigo
* @return void
*/
public function setCodigo($newCodigo) {
$this->codigo = $newCodigo;
}
/**
* @OneToOne(fetch=FetchType.FETCH,cascade=CascadeType.ALL)
* @return PessoaFisica
*/
public function getPF() {
return $this->pF;
}
/**
* @param PessoaFisica $newPF
* @return void
*/
public function setPF(PessoaFisica $newPF) {
$this->pF = $newPF;
}
/**
* @param int $newId
* @return void
*/
public function setIdPF($newId) {
$this->getPF()->setId($newId);
}
/**
* @return int
*/
public function getIdPF() {
return $this->getPF()->getId();
}
/**
* @return string
*/
public function getRg() {
return $this->getPF()->getRg();
}
/**
* @param string $newRg
* @return void
*/
public function setRg($newRg) {
$this->getPF()->setRg($newRg);
}
}
/**
* Engine PHP Application Framework
* http://seelaz.com.br
* File: IPessoaFisica .php
**/
/**
* @author Silas R. N. Junior
*/
interface IPessoaFisica {
/**
* @param int $newId
* @return void
*/
public function setIdPF($newId);
/**
* @return int
*/
public function getIdPF();
/**
* @return string
*/
public function getRg();
/**
* @param string $newRg
* @return void
*/
public function setRg($newRg);
}
/**
* Engine PHP Application Framework
* http://seelaz.com.br
* File: Telefone.php
**/
/**
*/
class Telefone {
/**
* @Id
* @var int
*/
private $id;
/**
* @var int
*/
private $ddd;
/**
* @var int
*/
private $numero;
/**
* @var PessoaFisica
*/
private $pessoa;
/**
* @return int
*/
public function getId() {
return $this->id;
}
/**
* @param int $newId
* @return void
*/
public function setId($newId) {
$this->id = $newId;
}
/**
* @return int
*/
public function getDdd() {
return $this->ddd;
}
/**
* @param int $newDdd
* @return void
*/
public function setDdd($newDdd) {
$this->ddd = $newDdd;
}
/**
* @return int
*/
public function getNumero() {
return $this->numero;
}
/**
* @param int $newNumero
* @return void
*/
public function setNumero($newNumero) {
$this->numero = $newNumero;
}
/**
* @ManyToOne
* @return PessoaFisica
*/
public function getPessoa() {
return $this->pessoa;
}
/**
* @param PessoaFisica $newPessoa
* @return void
*/
public function setPessoa(PessoaFisica $newPessoa) {
$this->pessoa = $newPessoa;
}
}
Criando a base de dados.
MySQL
CREATE TABLE IF NOT EXISTS `PessoaFisica` ( `id` int(11) NOT NULL auto_increment, `rg` varchar(7) NOT NULL, PRIMARY KEY (`id`), KEY `rg` (`rg`) ) ENGINE=InnoDB; CREATE TABLE IF NOT EXISTS `Cliente` ( `id` int(10) unsigned NOT NULL auto_increment, `codigo` int(11) default NULL, `pF` int(11) default NULL, PRIMARY KEY (`id`), KEY `FK_clientePessoaFisica` (`pF`) ) ENGINE=InnoDB; CREATE TABLE IF NOT EXISTS `Telefone` ( `id` int(11) NOT NULL auto_increment, `ddd` int(11) NOT NULL, `numero` int(11) NOT NULL, `pessoa` int(11) NOT NULL, PRIMARY KEY (`id`), KEY `FK_pessoaFisica` (`pessoa`) ) ENGINE=InnoDB; ALTER TABLE `Cliente` ADD CONSTRAINT `cliente_ibfk_1` FOREIGN KEY (`pF`) REFERENCES `PessoaFisica` (`id`); ALTER TABLE `Telefone` ADD CONSTRAINT `telefone_ibfk_1` FOREIGN KEY (`pessoa`) REFERENCES `PessoaFisica` (`id`);
PostgreSQL
CREATE TABLE "PessoaFisica"
(
id serial NOT NULL,
rg character varying(7),
CONSTRAINT "PK_pessoaFisica" PRIMARY KEY (id)
)
WITH (OIDS=TRUE);
CREATE TABLE "Cliente"
(
id serial NOT NULL,
codigo integer,
"pF" integer,
CONSTRAINT "PK_cliente" PRIMARY KEY (id),
CONSTRAINT "FK_pessoaFisica" FOREIGN KEY ("pF")
REFERENCES "PessoaFisica" (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (OIDS=TRUE);
CREATE TABLE "Telefone"
(
id serial NOT NULL,
ddd integer,
numero integer,
pessoa integer,
CONSTRAINT "PK_telefone" PRIMARY KEY (id),
CONSTRAINT "FK_pessoaFisica" FOREIGN KEY (pessoa)
REFERENCES "PessoaFisica" (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (OIDS=TRUE);
E agora ao código em si:
require_once("lib/engine/engine.db.php");
//Exemplos de como se criar o driver
//$driver = DbDriverFactory::getDriver(DbDriver::MYSQL);
//$driver = DbDriverFactory::getDriver(DbDriver::PGSQL);
//Para nosso tutorial utilizaremos o MySQL, portanto:
$driver = DbDriverFactory::getDriver(DbDriver::MYSQL);
$driver->configure('<host>','<base_de_dados_ou_schema>','user','pass');
//Criar o DAO
$dao = new DAO($driver);
//Instanciar nossas Entidades
$pessoa = new PessoaFisica();
$cliente = new Cliente();
$pessoa ->setRg('1111'); //PessoaFisica.rg
$cliente ->setCodigo(12345); //Cliente.codigo
$cliente->setPF($pessoa); //Setando a pessoa em cliente
//Telefones
$tel1 = new Telefone();
$tel1->setDdd(new Integer(62));
$tel1->setNumero(new Integer(1111));
$tel1->setPessoa($pessoa);
$tel2 = new Telefone();
$tel2->setDdd(new Integer(62));
$tel2->setNumero(new Integer(2222));
$tel2->setPessoa($pessoa);
$col = new Collection();
$col->add($tel1);
$col->add($tel2);
$pessoa->setTelefones($col);
//Gravar
$dao->save($cliente);
//O id é setado automaticamente apos a inserção. Vamos gurdá-lo para carregar a entidade.
$id = $cliente->getId();
unset($cliente);
// Criar uma outra instancia da classe.
$cliente2 = new Cliente();
// Definir o Id que corresponde a entidade no banco
$cliente2->setId($id);
//Carregar os dados
$dao->load($cliente2);
//Confirmar:
echo $cliente2->getRg();
//Modificar no banco:
$cliente2->setRg('2222');
$cliente2->setCodigo('567890');
//Gravar
$dao->save($cliente2);
//Agora para excluir a entidade
$dao->delete($cliente2);
Bom é isso. No proximo artigo vou mostrar como utilizar coleções (MantToMany) com o Engine.DB. Até lá!