Página Inicial > tutoriais > Usando o Engine.DB – Parte 3

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.

objcomposicao-pessoafisica-cliente

[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);

Download do Código-fonte

Bom é isso. No proximo artigo vou mostrar como utilizar coleções com o Engine.DB. Até lá!

  1. leandro n. camargo
    8, abril, 2009 em 20:32 | #1

    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.

  2. 8, abril, 2009 em 21:04 | #2

    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.

  3. leandro n. camargo
    8, abril, 2009 em 21:21 | #3

    Ah sim, achei que que os getters e setter eram gerados através de algum gerador de código da sua framework.

  4. 12, abril, 2009 em 02:54 | #4

    Adoro php! _o/

  5. 16, abril, 2009 em 17:49 | #5

    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/

  6. Douglas Rossignolli
    18, agosto, 2011 em 11:50 | #6

    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 )

  1. Nenhum trackback ainda.