Construindo Uma Arquitetura de Desenvolvimento em PHP 5
Construindo Uma Arquitetura de Desenvolvimento em PHP 5
Construindo Uma Arquitetura de Desenvolvimento em PHP 5
Rogério Rodrigues (e-mail) trabalha com Desenvolvimento de Sistemas, Modelagem de Dados, Programação
em PHP e Java na Agência Espacial Brasileira. Faz bacharelado em Ciência da Computação, desenvolve
trabalhos free-lancer para vários tipos de serviços Web.
Iremos, nesse artigo, entender como funciona um Sistema divido em Camadas e construir uma classe de
manipulação de Banco de Dados.
Pré-Requisitos
Introdução
O PHP vem crescendo muito e está sendo usado hoje em dia em desenvolvimento de software e vou falar
e mostrar exemplos práticos ao longo do tempo sobre esse tipo de aplicação com o php. Geralmente,
quando construímos aplicações pequenas ou de fácil interação, nós, “falando de programação”,
colocamos a “lógica do negócio” nas mesmas páginas e não nos preocupamos muito com a divisão da
lógica de programação em partes.
Mas para aplicações de médio e grande porte (E-Commerce, Portais, etc) se fizermos isso, iremos com
certeza cair em uma bagunça que não teremos mais volta, já vi muito dessas coisas aconterem com
pessoas conhecidas, é por isso que eu vou conceituar e construir uma “Arquitetura de Desenvolvimento”
para nosso sistema ganhar mais performance e abrangência. Também conhecida como arquitetura das
três camadas (Banco de Dados, Regras de Negócio e Interface com o Usuário).
Entendendo
Interface com o Usuário - Entrada e saída de dados. A única visão do sistema pelo usuário.
Regras de Negócio - São Classes que validam do dados vindo da Interface com Usuário, retornam
mensagens de erro quando houverem. Também responsável por levar e trazer informações do Banco de
Dados.
Banco de Dados - Camada responsável pela comunicação e manutenção de dados e informações.
Agora, como construir esse tipo de aplicação? Bom, iremos precisar de uma Pattern, o que seria isso?
Uma organização das camadas. Veja a figura abaixo e compreenda.
A pasta mãe eu chamo de fábrica porque nós estamos propondo uma fábrica de software (pelos menos a
pattern), neste artigo não irei falar sobre levantamento e requisitos.
A pasta Arquitetura irá conter as classes utilitárias do sistema, ex: Banco de Dados, E-mail, Manipulação
de Arquivos, etc.
A pasta Negócio conterá as classes que compôem a lógica dos nossos sistemas. Já a pasta Sistema
conterá as páginas que farão a troca de dados com o usuário.
Agora, sabendo disso, iremos construir uma pequena aplicação com esse conceitos.
A Arquitetura
Na pasta Arquitetura ficam as classes utilitárias dos aplicativos a serem criados, veremos agora a classe
que manipula o banco de dados (usarei o MySQL, mas nada impede de usar outro banco).
class BancodeDados {
private $host;
private $username;
private $password;
private $connection;
private $squema;
$xml = simplexml_load_file($resource);
$this->host = $xml->sessionfactory->host;
$this->username = $xml->sessionfactory->username;
$this->password = $xml->sessionfactory->password;
$this->squema = $xml->sessionfactory->database;
return $this->connection;
mysql_close($this->connection);
$retorno = mysql_query($sql,$this->connection);
return $retorno;
$this->executaSQL("begin");
$this->executaSQL("commit");
$this->executaSQL("rollback");
Entendendo o código
A classe receberá os atributos host, username, password e squema para fazer a conexão.
Estes atributos vindos de um arquivo xml. Sendo que o caminho desse arquivo é passado como
parâmetro no método construtor.
--version 1.0--
--configuration--
--sessionfactory--
--host--localhost--/host--
--username--root--/username--
--password--abc--/password--
--database--exclusiva--/database--
--/sessionfactory--
--/configuration--
No método construtor os atributos são inicializados com os dados vindos do XML. O método updateSQL()
executa a query e retorna true ou false. O método executaSQL() executa a query e retorna os registros.
Os métodos iniciarTransacao(), efetivarTransacao() e desfazerTransacao() são para transação de banco
de dados.
Com isso, nós já temos uma parte das camadas prontas, uma parte da camada Banco de Dados com a
classe manipuladora. Separamos o código que geralmente é posto onde você recebe os dados e já
conecta e executa tudo. Agora, nós temos um objeto que irá fazer isso, acontecendo também o re-uso de
código porque toda aplicação que necessitar interagir com o banco de dados irá usar o objeto
BancodeDados.
Olá pessoal. Já vimos no artigo passado a camada "arquitetura", onde criamos uma classe de
manipulação de banco de dados (na arquitetura ficam as classes utilitárias comuns a todos os
sitemas ex: BancoDeDados, Manipulação de Arquivos, E-mail, etc), que será usada pela nossa
aplicação e para várias outras que vocês queiram fazer.
Estudo de Caso
Vamos pegar um caso MUITO simples para o entendimento de todos. Tenho um site e quero ter o
cadastro de meus clientes para no futuro eu poder fazer propagandas, estatísticas, etc. Agora que já
temos o nosso objetivo, vamos começar a pensar em objetos.
Quem tem atributos e realiza ações? Neste nosso caso é somente o Cliente. Então só teremos o objeto
Cliente.
E quando estamos falando das funções do sistema estamos falando do NEGÓCIO do sistema. Estamos
saindo da camada da Arquitetura e entrando na cadama Negocial.
Procedimento: Na pasta negocio crie uma pasta com o nome do sistema, no nosso caso é a pasta
"siscliente" (sistema de cliente) e dentro dela a pasta "cliente" e dentro dessa pasta vamos criar a
entidade (classe) Cliente.
Cliente.class.php
class Cliente {
private $codigo;
private $nome;
private $telefone;
private $email;
private $endereco;
A diferença entre a Entidade e o Objeto DAO. A entidade somente conterá os atributos e os métodos de
acesso a esses métodos.
O DAO conterá os métodos que realizam as ações (incluir,alterar,etc) da Entidade relacionada. Ou seja,
para cada Objeto.class.php e esse objeto realiza operações existirá um ObjetoDAO.class.php.
O Data Access Object (DAO) significa "Objeto de acesso ao Banco", ou seja todas as operações que
necessitarem manter alguma informação com o banco de dados será essa classe que fará a
manipulação.
Olá pessoas. Conversaremos hoje sobre o o Data Access Object (DAO). Como estou falando da parte
negocial do sistema, veremos uma classe que terá o acesso ao banco de dados para realizar as
operações de busca, inserção, etc.
Como a nossa proposta é separar em camadas a nossa aplicação, construiremos um "módulo" que fará a
persistência com o banco de dados. Teremos uma classe que fará o transporte do banco e outra mais
específica que executará as funções.
Cada "Entidade" (classe) que necessita fazer transações com o banco de dados terá uma classe DAO
associada a ele. No caso, irei fazer a classe para a nossa entidade Cliente, que vimos no artigo passado.
A classe conterá somente métodos que realizarão funções com o objeto. Construiremos 5 métodos:
incluir, recuperarTodos, recuperarPorId, alterar e excluir.
Procedimento: Na pasta "cliente" criaremos o arquivo ClienteDAO.class.php
ClienteDAO.class.php
require_once("../../../arquitetura/DAO.class.php");
$banco = $this->getBancoDados();
if(!$banco->updateSQL($sql)) {
throw new Exception("ERRO NA QUERY CLIENTEDAO MÉTODO INSERIR
CLIENTE");
}
}
$banco = $this->getBancoDados();
$cliente = NULL;
$retorno = $banco->executaSQL($sql);
if($retorno != NULL) {
while($linha = mysql_fetch_array($retorno)) {
$cliente = new Cliente();
$cliente->setCodigo($linha["id"]);
$cliente->setNome($linha["nome"]);
$cliente->setEmail($linha["email"]);
$cliente->setEndereco($linha["endereco"]);
$cliente->setTelefone($linha["telefone"]);
}
return $cliente;
} else {
throw new Exception("ERRO NA QUERY CLIENTEDAO MÉTODO RECUPERAR
CLIENTE POR ID");
}
}
$banco = $this->getBancoDados();
$retorno = $banco->executaSQL($sql);
if($retorno != NULL) {
$clientes = NULL;
$i = "0";
while($linha = mysql_fetch_array($retorno)) {
$clientes[$i] = $this->recuperarPorId($linha["id"]);
$i++;
}
return $clientes;
} else {
throw new Exception("ERRO NA QUERY CLIENTEDAO MÉTODO RECUPERAR
CLIENTE TODOS");
}
}
}
Na pasta arquitetura crie um arquivo chamado DAO.class.php, ele será o nosso Data
Access Object.
DAO.class.php
class DAO {
public $banco;
$this->banco = $banco;
return $this->banco;
O método inserirCliente recebe como parâmetro o objeto cliente e constrói a query com os dados do
cliente. A classe estende a classe DAO (requerida da pasta arquitetura) que tem os métodos
setBancoDados e getBancoDados.
Estes dois métodos são chamados quando instanciamos o ClienteDAO e passo o objeto BancodeDados
já conectado (passado por referência). A classe usa esse objeto banco para realizar as operações.
Espero ter ajudado a entender o objeto DAO. No próximo artigo, veremos como funciona a SESSION
FACADE (lê-se façeide), que é onde estão as regras de negócio do nosso sistema.
USE TEST;
CREATE TABLE cliente
(
id INT NOT NULL AUTO_INCREMENT,
nome VARCHAR(255) NOT NULL,
telefone VARCHAR(255) NOT NULL,
endereco VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL,
PRIMARY KEY(id)
);
Abraço!
Construindo uma Arquitetura de Desenvolvimento em PHP 5 -
Parte 04
Rogério Rodrigues (e-mail) trabalha com Desenvolvimento de Sistemas, Modelagem de Dados, Programação
em PHP e Java na Agência Espacial Brasileira. Faz bacharelado em Ciência da Computação, desenvolve
trabalhos free-lancer para vários tipos de serviços Web.
A Session Facade tem um conjunto de métodos de negócio, responsável por acessar e atualizar dados. É
um ponto de entrada único dos dados e funcionalidades. É uma camada de controle da lógica de negócio
da aplicação. Construiremos os métodos inserirCliente e recuperarClientes.
IMPORTANTE: No caso só uma session façade para o sistema, no caso de muitas classe, esse session
irá controlar toda a lógica delas, ou seja, toda a lógica de negócio do sistema será controlada pela façade.
SessionFacade.class.php
SessionFacade.class.php
require_once("cliente/Cliente.class.php");
require_once("cliente/ClienteDAO.class.php");
class SessionFacade {
public $banco;
if($cliente->getNome() == NULL) {
throw new Exception("O NOME É UM CAMPO OBRIGATÓRIO");
}
if($cliente->getTelefone() == NULL) {
throw new Exception("O TELEFONE É UM CAMPO OBRIGATÓRIO");
}
if($cliente->getEndereco() == NULL) {
throw new Exception("O ENDEREÇO É UM CAMPO OBRIGATÓRIO");
}
$clienteDAO->inserir($cliente);
return $clienteDAO->recuperarTodos();
}
/* PARA OS MÉTODOS DE ALTERAR E EXCLUIR SEGUE O MESMO PROCEDIMENTO, PODENDO
TAMBÉM SER FEITOS MÉTODOS PARA REALIZAR FUNÇÕES, EX: RECUPERARPORDATA, ETC. */
O método construtor recebe como parâmetro o banco de dados passado por referência, e o atribui a
variável banco que será usada pelos métodos.
A validação dos dados eu faço com excessões que serão disparadas quando o dado não estiver de
acordo com a regra.
Instancio o ClienteDAO, passo o banco por referência já conectado para o objeto usá-lo. Caso haja algum
erro no ClienteDAO, lá é disparada uma excessão. É preciso dar um require_once das classes que serão
usadas sempre.
Assim funciona a SessionFacade. Se houver mais classes, elas também são controladas nesta session.
No próximo artigo veremos como funciona a chamada da façade e a passagem de parâmetros.
Abraço!
Continuando a série, chegamos a uma parte que eu considero um comunicador entre a interface e a
lógica do sistema - a Manter.
Os modos de acessar a Manter serão formulários e links passando dados para a operações serem
realizadas.
Procedimento: Na pasta "Sistema em Fábrica" iremos criar a pasta "siscliente", semelhante a negócio, e
dentro dela o arquivo manterCliente.php.
manterCliente.class.php
require_once("../../../arquitetura/BancodeDados.class.php");
require_once("../../../negocio/siscliente/SessionFacade.class.php");
require_once("../../../negocio/siscliente/cliente/Cliente.class.php");
@session_start();
if(!isset($_SESSION["clientes"])) {
$_SESSION["clientes"] = NULL;
}
if(isset($_POST["acao"])) {
if($_POST["acao"] == "Cadastrar") {
cadastrar();
}
}
if(isset($_GET["acao"])) {
if($_GET["acao"] == "Mostrar") {
mostrarClientes();
}
}
function cadastrar() {
$banco = new BancodeDados("../../../sistema/siscliente/conexao.xml");
$sessionFacade = new SessionFacade($banco);
try {
$banco->conecta();
$sessionFacade->inserirCliente($cliente);
$banco->desconecta();
header("location: cadastrarCliente.php?msg=OPERAÇÃO REALIZADA COM
SUCESSO");
} catch(Exception $e) {
$banco->desconecta();
header("location: cadastrarCliente.php?msg=".$e->getMessage());
}
function mostrarClientes() {
$banco = new BancodeDados("../../../sistema/siscliente/conexao.xml");
$sessionFacade = new SessionFacade($banco);
try {
$banco->conecta();
$_SESSION["clientes"] = $sessionFacade->recuperarClientes();
$banco->desconecta();
header("location: mostrarClientes.php");
} catch(Exception $e) {
$banco->desconecta();
header("location: mostrarClientes.php?msg=".$e->getMessage());
}
No início, eu coloco as classes que eu irei utilizar e inicio a sessão com session_start. A primeira condição
que eu analiso é se as sessões que eu irei utilizar já existem, caso não, eu as crio sendo nulas.
A segunda é verificar se existe algum request vindo de formulário que eu nomeio como "ação" (no caso,
eu julgo ações ).
Para cada tipo de ação irá existir uma função para tratar da execução.
Como funciona a classe BancodeDados está explicada na segunda parte desta série de artigos. No
próximo artigo veremos as entradas e saídas de dados.
Construindo uma Arquitetura de Desenvolvimento em PHP 5 -
Parte 05
Rogério Rodrigues (e-mail) trabalha com Desenvolvimento de Sistemas, Modelagem de Dados, Programação
em PHP e Java na Agência Espacial Brasileira. Faz bacharelado em Ciência da Computação, desenvolve
trabalhos free-lancer para vários tipos de serviços Web.
Continuando a série, chegamos a uma parte que eu considero um comunicador entre a interface e a
lógica do sistema - a Manter.
Os modos de acessar a Manter serão formulários e links passando dados para a operações serem
realizadas.
Procedimento: Na pasta "Sistema em Fábrica" iremos criar a pasta "siscliente", semelhante a negócio, e
dentro dela o arquivo manterCliente.php.
manterCliente.class.php
require_once("../../../arquitetura/BancodeDados.class.php");
require_once("../../../negocio/siscliente/SessionFacade.class.php");
require_once("../../../negocio/siscliente/cliente/Cliente.class.php");
@session_start();
if(!isset($_SESSION["clientes"])) {
$_SESSION["clientes"] = NULL;
}
if(isset($_POST["acao"])) {
if($_POST["acao"] == "Cadastrar") {
cadastrar();
}
}
if(isset($_GET["acao"])) {
if($_GET["acao"] == "Mostrar") {
mostrarClientes();
}
}
function cadastrar() {
$banco = new BancodeDados("../../../sistema/siscliente/conexao.xml");
$sessionFacade = new SessionFacade($banco);
try {
$banco->conecta();
$sessionFacade->inserirCliente($cliente);
$banco->desconecta();
header("location: cadastrarCliente.php?msg=OPERAÇÃO REALIZADA COM
SUCESSO");
} catch(Exception $e) {
$banco->desconecta();
header("location: cadastrarCliente.php?msg=".$e->getMessage());
}
function mostrarClientes() {
$banco = new BancodeDados("../../../sistema/siscliente/conexao.xml");
$sessionFacade = new SessionFacade($banco);
try {
$banco->conecta();
$_SESSION["clientes"] = $sessionFacade->recuperarClientes();
$banco->desconecta();
header("location: mostrarClientes.php");
} catch(Exception $e) {
$banco->desconecta();
header("location: mostrarClientes.php?msg=".$e->getMessage());
}
No início, eu coloco as classes que eu irei utilizar e inicio a sessão com session_start. A primeira condição
que eu analiso é se as sessões que eu irei utilizar já existem, caso não, eu as crio sendo nulas.
A segunda é verificar se existe algum request vindo de formulário que eu nomeio como "ação" (no caso,
eu julgo ações ).
Para cada tipo de ação irá existir uma função para tratar da execução.
Como funciona a classe BancodeDados está explicada na segunda parte desta série de artigos. No
próximo artigo veremos as entradas e saídas de dados.
Olá a todos. Nesta etapa vamos criar um layout para a entrada de dados, que será um simples formulário.
Será uma etapa bem curta. Lembrando que é importante que o leitor acompanhe as matérias anteriores
desta série. Todas as matérias estão listadas ao final deste artigo.
cadastrarCliente.php
<html>
<body>
<?php if(isset($_GET["msg"])) {
print $_GET["msg"];
} ?>
<form method="post" action="manterCliente.php">
<input type="text" name="nome" value="nome"><br>
<input type="text" name="telefone" value="telefone"><br>
<input type="text" name="endereco" value="endereco"><br>
<input type="text" name="email" value="email"><br>
<input type="submit" name="acao" value="Cadastrar">
</form>
<a href="manterCliente.php?acao=Mostrar">mostrar Clientes</a>
</body>
</html>
Neste formulário estou colocando a ação como "Cadastrar". Ou seja, esse formulário irá acessar na
manter a função cadastrar.
mostrarClientes.php
<?php
require_once("../../../negocio/siscliente/cliente/Cliente.class.php");
@session_start();
?>
<html>
<body>
<?php
for($i= 0; $i < sizeof($_SESSION["clientes"]); $i++) {
print "nome: ".$_SESSION["clientes"][$i]->getNome();
print "<br>";
}
?>
</body>
</html>
Nesta página eu incluo a classe que será usada e faço um laço para mostrar os resultados que estão na
sessão.
No próximo e último artigo desta série farei uma explicação geral de como e quando usar outros design
patterns que podem ser utilizadas, aplicação em ambiente corporativo, ganhos e perdas, dentre outros.
Até mais!