Diego Botelho Martins

NOTE: To use the advanced features of this site you need javascript turned on.

Home Artigos PHP Mapeamento Objeto-Relacional da Teoria à Prática
Mapeamento Objeto-Relacional da Teoria à Prática PDF Imprimir E-mail
Escrito por Diego Botelho   
Dom, 25 de Outubro de 2009 00:00
Índice do Artigo
Mapeamento Objeto-Relacional da Teoria à Prática
Introdução
A Classe Cliente.php
Todas as Páginas

Nota: Artigo publicado originalmente no portal PHP Brasil em 2007 e devido a tamanha repercussão resolvi disponibilizá-lo também aqui no site.

Neste artigo irei falar resumidamente sobre mapeamento objeto-relacional que consiste em uma
abordagem que permite a construção de sistemas utilizando o paradigma da orientação a objetos com a persistência destes objetos em bancos de dados relacionais como o Mysql.


Utilizando-se de técnicas e estratégias específicas, é possível mapear classes com seus atributos e associações para o modelo relacional.

Os bancos de dados orientados a objeto são mais adequados para a persistência de objetos manipulados por aplicações orientadas a objeto, devido à utilização do mesmo paradigma. Porém a indisponibilidade atual destes bancos de dados, seja devido ao custo, diversidade ou amadurecimento do mercado, faz com que seja necessária a busca de alternativas para a realização da persistência.

Desenvolvendo projetos desta maneira você estará contribuindo para a reutilização do seu código em diferentes áreas do seu sistema e até mesmo de projetos futuros, sem falar da legibilidade e do aspecto profissional agregados ao seu código.

Mais como seria esse mapeamento na prática?

Suponha que tenhamos as seguintes tabelas do DER abaixo no nosso banco de dados:




A partir delas iremos construir nossas classes, lembrando que a ordem não importa, conheço
algumas pessoas que costumam fazer a modelagem do banco de dados primeiro, depois as tabelas
e outras que modelam primeiro seus objetos para somente então, partir para a construção do DER.

Abaixo está o diagrama de classes que representa as tabelas do DER:

Obs.: Sinais de visibilidade de atributos e métodos utilizados seguindo os padrões da UML

Onde o sinal de "+" => private; "-" => public; "#" => protected





No diagrama de classes, cada tabela do banco de dados foi mapeada para uma classe, onde
o nome da classe é o mesmo nome da tabela só que no singular e sem o prefixo.

Os atributos possuem visibilidade private, ou seja, somente os métodos internos a classe
é que poderão acessá-los diretamente, para objetos externos acessarem estes atributos,
deve-se utilizar as propriedades modificadoras, os famosos get e set, se o atributo for
somente de leitura você pode omitir a propriedade set.

O método __construct pode ser utilizado para setar os valores default de cada atributo.

Relacionamentos:

No DER temos o relacionamento 1 para n indicando que uma categoria pode conter nenhum
ou vários clientes, porém um cliente só está ligado a uma categoria.
Para construir o relacionamento inserimos a chave estrangeira cli_idCategoria na tabela
de clientes ligando-a com a chave primária cat_id da tabela de categorias.
No diagrama de classes também temos os atributos cli_idCategoria e cat_id, só que como
o objeto Cliente é responsável por conhecer a sua categoria, criamos o atributo objCategoria
na classe Cliente, desta forma, assim que utilizarmos o método $objCliente->carregar(),
este terá que chamar o método $this->objCategoria->carregar().
Estes métodos devem recuperar os dados de um determinado registro no banco e setá-los
em cada atributo do objeto.

Para que possamos identificar qual registro deve ser recuperado, setamos o id do objeto:



A implementação dos métodos CRUD (Create, Read, Update e Delete), ou seja, cadastrar, carregar,
alterar e excluir, vai depender de quantas camadas sua aplicação estará dividida.

O ideal é que nas classes Cliente e Categoria você só realize operações envolvidas com a camada
de negócios, fazendo com que estes métodos chamem outros métodos de uma camada de nível
mais baixo, como por exemplo DaoCliente::carregar() e DaoCategoria::carregar().
(Dao vem de Data Access Object)

Estas classes sim é que poderiam ter métodos com cláusulas SQL como SELECT, INSERT, UPDATE E DELETE.

Da mesma forma, você pode criar classes de nível mais alto para gerenciar a camada de
apresentação, nestas classes você irá tratar códigos HTML, Javascript, CSS e etc.

Codificando desta forma seus objetos ficarão muito mais reutilizáveis!!

Então chega de conversa e mãos a obra! Na próxima página postei o código fonte das classes.



<?php

class ClienteException extends Exception { }

/**
* Classe responsável pelo gerenciamento das informações de um cliente
*
* @package MeuSistema
* @subpackage Clientes
* @author Diego Botelho < Este endereço de e-mail está protegido contra spambots. Você deve habilitar o JavaScript para visualizá-lo. >
* @link http://www.diegobotelho.com.br
* @date 2007-01-30 21:07:00
*/
class Cliente
{
/**
* @var int
* @access private
*/
private $cli_id;

/**
*
* @var int
* @access private
*/
private $cli_idCategoria;

/**
* @var object
* @access private
*/
private $objIdCategoria;

/**
* @var string
* @access private
*/
private $cli_nome;

/**
* @var string
* @access private
*/
private $cli_cpf;

/**
* @var string
* @access private
*/
private $cli_email;

//----------------------------------------------------------------------

/**
* Seta o valor do atributo $cli_id
* @param int $intId
* @access public
*/
public function setId($intId)
{
$this->cli_id = $intId;
}

/**
* Obtém o valor do atributo $cli_id
* @access public
*/
public function getId()
{
return $this->cli_id;
}

//... A mesma coisa para os outros atributos

//----------------------------------------------------------------------

/**
* Construtor da classe
* @access public
*/
public function __construct()
{
$this->setId("");
$this->setIdCategoria("");
$this->setCategoria(new Categoria);
$this->setNome("");
$this->setCpf("");
$this->setEmail("");
}

/**
* Destrutor da classe
* @access public
*/
public function __destruct(){}

/**
* Cadastra um novo cliente
* @access public
*/
public function cadastrar()
{
try {
DaoCliente::insert($this);
} catch(Exception $e) {
throw new ClienteException($e->getMessage());
}
}

/**
* Altera um cliente existente
* @access public
*/
public function alterar()
{
try {
DaoCliente::update($this);
} catch(Exception $e) {
throw new ClienteException($e->getMessage());
}
}

/**
* Exclui um cliente existente
* @access public
*/
public function excluir()
{
try {
DaoCliente::delete($this);
} catch(Exception $e) {
throw new ClienteException($e->getMessage());
}
}

/**
* Recupera um cliente armazenado em meio persistente
* @access public
*/
public function carregar()
{
try {
DaoCliente::load($this);

// Carregando a categoria do cliente
DaoCategoria::setId($this->idCategoria);
DaoCategoria::load($this->objCategoria);
} catch(Exception $e {
throw new ClienteException($e->getMessage());
}
}
}
?>



<?php
class CategoriaException extends Exception { }

/**
* Classe responsável pelo gerenciamento das informações de uma categoria
*
* @package MeuSistema
* @subpackage Categorias
* @author Diego Botelho < Este endereço de e-mail está protegido contra spambots. Você deve habilitar o JavaScript para visualizá-lo. >
* @link http://www.diegobotelho.com.br
* @date 2007-01-30 21:07:00
*/
class Categoria
{
/**
* @var int
* @access private
*/
private $cat_id;

/**
*
* @var string
* @access private
*/
private $cat_nome;

//----------------------------------------------------------------------

/**
* Seta o valor do atributo $cat_id
* @param int $intId
* @access public
*/
public function setId($intId)
{
$this->cat_id = $intId;
}

/**
* Obtém o valor do atributo $cat_id
* @access public
*/
public function getId()
{
return $this->cat_id;
}

/**
* Seta o valor do atributo $cat_nome
* @param int $strId
* @access public
*/
public function setNome($strNome)
{
$this->cat_nome = $strNome;
}

/**
* Obtém o valor do atributo $cat_nome
* @access public
*/
public function getNome()
{
return $this->cat_nome;
}

//----------------------------------------------------------------------

/**
* Construtor da classe
* @access public
*/
public function __construct()
{
$this->setId("");
$this->setNome("");
}

/**
* Destrutor da classe
* @access public
*/
public function __destruct() { }

/**
*
* Cadastra um nova categoria
* @access public
*/
public function cadastrar()
{
try {
DaoCategoria::insert($this);
} catch(Exception $e) {
throw new CategoriaException($e->getMessage());
}
}

/**
* Altera uma categoria existente
* @access public
*/
public function alterar()
{
try {
DaoCategoria::update($this);
} catch(Exception $e) {
throw new CategoriaException($e->getMessage());
}
}

/**
* Exclui uma categoria existente
* @access public
*/
public function excluir()
{
try {
DaoCategoria::delete($this);
} catch(Exception $e) {
throw new CategoriaException($e->getMessage());
}
}

/**
* Recupera uma categoria armazenado em meio persistente
* @access public
*/
public function carregar()
{
try {
DaoCategoria::load($this);
} catch(Exception $e) {
throw new CategoriaException($e->getMessage());
}
}

/**
* Retorna uma lista com as categorias cadastradas
* @access public
*/
public function listar()
{
try {
return DaoCategoria::collection($this);
} catch(Exception $e) {
throw new CategoriaException($e->getMessage());
}
}
}
?>


Bom é isso, apesar de ser bem superficial, espero que tenha ajudado.

Vale a pena programar orientado a objetos com PHP5!

Um abraço e até o próximo artigo!

Comentários
Adicionar novo Busca
Escrever um comentário
Nome:
E-mail:
 
Website:
Título:

3.26 Copyright (C) 2008 Compojoom.com / Copyright (C) 2007 Alain Georgette / Copyright (C) 2006 Frantisek Hliva. All rights reserved."

Última atualização em Seg, 14 de Dezembro de 2009 07:54
  Compartilhe no Orkut!