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/
Bem faz 2 anos esses comentários, mas pessoal que está entrando hoje e é novo pode fazer um set global da seguinte forma:
Crio a função da minha classe toArray();
/**
* Função para transformar os atributos da classe em Array
* @return array
*/
public function toArray() {
$props = array();
foreach ($this as $key => $value) {
if ($key[0] != “”) {
$props[$key] = $value;
}
}
return $props;
}
E criamos a função set() que recebe um array
public function set($atributos = array()){
if(is_array($atributos)){
foreach ($atributos as $atribKey => $atribValue) {
foreach ($this->toArray() as $propKey => $propValue) {
if($atribKey == $propKey){
$set = ‘set’.$propKey;
$this->$set($atribValue);
}
}
}
}
}
fazendo o teste temos:
$user = new Usuario();
$user->set(array(‘nome’=>’Meu Nome’,
‘rg’=>’99.999.999-X’));
Saida de dados ficou:
Array ( [id] => [rg] => 99.999.999-X [nome] => Renato Sala )