Usando o Engine.DB – Parte 3
Dando continuidade a nossa seção de tutoriais simples vamos aprender como o engine.DB trabalha com objetos compostos. Nesse exemplo eu apresentarei uma abordagem alternativa à herança, que eu utilizo atualmente.
Nossas entidades consistirão na nossa classe PessoaFisica, na classe Cliente (ligeiramente modificada do nosso tutorial anterior) e uma interface IPessoaFisica.

[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.
A utilização da interface se deve a necessidade de garantir que a classe Cliente se comporte como PessoaFisica também, fazendo com que ela apresente os acessors da classe “herdada”. O metodo para recuperar o ID da classe PessoaFisica tem um nome diferente pois Cliente ja possui um metodo de nome semelhante (getId) e o único proposito desse métido é facilitar o acesso a propriedade ID de forma direta. a chamada Cliente->getPF()->getId() tem resultado semelhante.
Definindo o relacionamento entra as entidades (1 pra 1) colocamos uma annotation no metodo getPF (por padrão, assim como no hibernate, é solicitado que se coloque as annotations de relacionamento nos getters) como especificado:
/** * @OneToOne(fetch=FetchType.FETCH,cascade=CascadeType.ALL) */
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.
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;
/**
* @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;
}
}
?>
<?php
/**
* 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;
/**
* @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);
}
}
?>
<?php
/**
* 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);
}
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`) ) 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;
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_clientePessoaFisica" FOREIGN KEY ("pF")
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
//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 com o Engine.DB. Até lá!
Acho interessante se houvesse a possbilidade de fazer algo como:
$cliente->setRg(’231211′)->setCodigo(321)->setPessoa($pessoa);
E ainda ter um setter global:
$cliente->set(array(’rg’ => ‘323112′, ‘codigo’ => 324, ‘pessoa’ => $pessoa));
Ambos deixam a programação mais prática.
No primeiro caso basta sempre retornar o $this nos setters.
Mas vc pode definir isso sim! O framework se baseia nas propriedades não transientes para gerar os sql. Essas implementações de acessors sao simples sendo que a primeira vc da um return $this depois que atribuir o valor a propriedade assim como vc falou, no outro caso vc prepara seu setter global do jeito que vc quiser (as vezes com um objeto que estuda suas propriedades e atribui os valores usando o indice do array). Mas os acessors padrão são obrigatórios, o framework reforça o uso de boas práticas. Se voce nao o fizer deverá aparecer algo sinistro na tela pq eu não testei sem ainda.. hehehehe.
Ah sim, achei que que os getters e setter eram gerados através de algum gerador de código da sua framework.
Adoro php! _o/
E aí Seelaz, blz?
Pois é, sempre dou uma passada por seu blog e outros pra ver algo de novo.
Então, eu trabalhei durante 4 anos com PHP e achei muito legal. É uma tecnologia muito rápida e legal de se trabalhar.
Trabalhava com o FastTemplate e achei bem legal. Iniciei a utilização de outros frameworks php, mas parei por ai pela mudança de trabalho.
Achei legal seu post sobre o tema. Esses dias de feriados estou tendo mais tempo e vou reservar um dia para apreciar o Engine.DB. E se eu ver algo de diferente nele vou sim dar um feedback pra ti.
Valeu d+ _o/