Escolar Documentos
Profissional Documentos
Cultura Documentos
Programao: Design
Pattern - MVC com PHP
Visite www.alfamidiaonline.com.br para outros
contedos e cursos gratuitos e pagos
Alfamdia Programao: Design Pattern - MVC com PHP
Todos os direitos reservados para Alfamdia Prow.
AVISO DE RESPONSABILIDADE
Alfamdia Prow
http://www.alfamidia.com.br
Unidade 1
PHP com MVC
1.1 Sobre o Curso
O Curso Sistemas de Comrcio Eletrnico com MVC com PHP apresenta aos alunos os
conceitos e tcnicas envolvidos no desenvolvimento de uma aplicao de comrcio
eletrnico.
Alm de compreender noes importantes, como validao de usurios e gerenciamento de
sesses.
Unidade 2
Padres de Projeto
2.1 Padres de Projeto
"Algum j resolveu os seus problemas!"
Unidade 3
As diferentes arquiteturas de Aplicaes
3.1 Aplicaes de Uma Camada
A estrutura fsica dos computadores sempre exerceu uma forte influencia no padro de
programao, seja limitando a quantidade de memria disponvel para rodar a aplicao ou
restringindo os recursos visuais que poderiam ser apresentados.
Neste sentido a programao, inicialmente era conhecida como monoltica, ou seja os papeis de
Apresentao dos dados, armazenamento e controle dos mesmos eram armazenados em um mesmo
computador.
O fato de inicialmente os computadores, de forma geral, serem de grande porte e via de regra no
possurem comunicao entre eles, tambm foi responsvel por esta necessidade de agrupamento
das camadas, mesmo que estas possuam papis diferenciados.
Este desenho de desenvolvimento trazia uma srie de complicadores para o desempenho de
construo, bem como para o processo de utilizao das mesmas. Dentre estes problemas podemos
citar: uma grande quantidade de linhas de cdigo e de manuteno extremamente complicada.
As camadas lgicas de entrada do usurio, verificao, lgica de negcio e acesso a banco de dados
estava presente em um mesmo lugar.
Visualmente podemos reproduzir a estrutura monoltica da seguinte forma:
Unidade 4
A arquitetura do padro MVC
4.1 Introduo
O Model-View-Controller (MVC) um padro de arquitetura de aplicao gerado a partir da
comunidade SmallTalk na dcada de 1970 por Reenskaug Trygve. E foi popularizada para uso na
web com o advento do Ruby on Rails em 2004.
A abordagem MVC composta por trs tipos de objetos:
Model (Modelo). Objetos que implementam a lgica para o domnio de dados do
aplicativo. Muitas vezes, os objetos do Modelo recuperam e armazenam seus estados em um banco
de dados. Por exemplo, um objeto Produto pode recuperar informaes de um banco de dados,
operar sobre elas, e em seguida, escrever informaes atualizadas de volta a uma tabela no banco de
dados.
View (Viso). Objeto que exibe a interface do aplicativo com o usurio (UI), criado a
partir dos dados do Modelo. Um exemplo de uma Viso seria a representao dos dados de um
objeto de modelo Produto, que apresenta ao usurio caixas de textos com informaes do Nome,
Descrio, Preo e Categoria do Produto.
Controller (Controle). So componentes que lidam com a interao do usurio, trabalhar
com o Modelo e, finalmente, toma a deciso de qual Viso mostrar. Em um aplicativo MVC, a
Viso exibe informaes de Modelo e o Controle manipula e responde a entrada do usurio em uma
interao.
O padro MVC ajuda a criar aplicaes que separam os diferentes aspectos da aplicao (lgica de
requisio/entrada, a lgica do negcio e lgica UI), proporcionando um acoplamento fraco entre
esses elementos. O padro especifica onde cada tipo de lgica deve ser estar na aplicao. A lgica
da interface do usurio pertence Viso. Lgica de requisio/entrada pertence ao Controller. A
lgica do negcio pertence ao Modelo. Esta separao ajuda voc a gerenciar a complexidade
quando voc cria um aplicativo, porque ele permite que voc concentre-se em um aspecto da
aplicao de cada vez. Por exemplo, voc pode se concentrar na viso sem depender da lgica de
negcios.
Unidade 5
Criando uma aplicao MVC
Vamos construir uma aplicao usando MVC com PHP que consistir em um sistema de
gerenciamento de produtos para loja virtual. Essa aplicao ter um controle de acesso que ir
incluir, ler, atualizar e excluir (CRUD = create, read, update, delete) produtos do catlogo de uma
loja virtual.
-- -----------------------------------------------------
-- TABELA fabricante
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `fabricante` (
id INT(11) NOT NULL AUTO_INCREMENT,
nome VARCHAR(80) NULL, PRIMARY KEY (id)
) ENGINE=InnoDB;
-- -----------------------------------------------------
-- TABELA linha
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS linha (
id INT(11) NOT NULL AUTO_INCREMENT,
nome VARCHAR(80) NULL, PRIMARY KEY (id)
) ENGINE=InnoDB;
-- -----------------------------------------------------
-- TABELA produto
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS produto (
id INT(11) NOT NULL AUTO_INCREMENT,
linha_id INT(11) NOT NULL,
fabricante_id INT(11) NOT NULL,
nome VARCHAR(100) NOT NULL,
descricao MEDIUMTEXT NULL,
preco FLOAT NULL,
peso FLOAT NULL,
imagem VARCHAR(100) NULL,
destaque TINYINT(1) NULL,
qtd_estoque FLOAT NULL,
Tambm vamos criar e alimentar uma tabela para o login do usurio no sistema:
-- -----------------------------------------------------
-- TABELA usuario
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS usuario (
login VARCHAR(15) NOT NULL ,
senha VARCHAR(50) NULL ,
PRIMARY KEY (login)
)ENGINE = InnoDB;
Repare que no vamos armazenar a senha da maneira usual, simplesmente guardando o seu valor no
banco de dados. Isso deixaria o usurio utilizador do sistema vulnervel, pois se o mesmo utilizar a
sua senha em mais de um sistema, ele ficaria exposto em caso de invaso ao nosso site.
Por isso vamos usar a funo MD5 para gerar um HASH da mesma. Hash, em termos mais
tcnicos, uma sequncia de caracteres (letras ou nmeros) gerada por um algoritmo de disperso
que transforma uma (possvel) grande quantidade de dados em uma pequena quantidade de forma
quase exclusiva.
A seqencia de Hash busca identificar uma informao de maneira nica, sendo um mtodo para
transformar dados visando um resultado exclusivo.Por exemplo, criando identificaes para uma
mensagem de correio eletrnico, uma senha, uma chave criptogrfica ou mesmo um arquivo.
No nosso caso, o HASH gerado pela senha do usurio ser armazenado no banco. No h como
descobrir qual senha gerou aquele HASH. A nica maneira possvel so os mtodos de fora bruta,
onde o atacante tenta adivinhar qual a senha que gera um determinado HASH.
Para verificarmos se um usurio autntico no sistema, vamos aplicar a funo MD5 sobre a senha
fornecida e verificar se igual ao HASH armazenado.
As pastas css, images e js iro conter os arquivos de css, imagens e Java script respectivamente. A
pasta helpers conter as classes de terceiros que vamos utilizar para desenvolver o sistema e a pasta
system, todos os objetos e arquivos de configurao. A pasta system ir conter os arquivos de
configurao do sistema e tambm as classes que iro compor
Dentre estes modelos, que chamamos de Templates, podemos destacar o Template Power e o
Smarty. Vamos utilizar o Template Power para nos ajudar a implementar esse conceito do MVC.
Caso deseje conhecer mais sobre o Template Power acesse: http://templatepower.codocad.com/ e
para obter mais informaes sobre o Smarty acesse: http://www.smarty.net/.
Arquivo: helpers/class.Upload.inc.php
<?php
/**
* Classe para tratamento de Upload de arquivos
*
*/
class Upload
{
// propridades da classe
public $Campo;
public $Arquivo;
public $PastaDestino;
public $Sobrescrever;
public $ehUpload;
public $Erro = 0;
// extenses aceitas por default para upload
public $ExtValidas = array('jpeg', 'jpg', 'jpe', 'gif', 'png');
/**
* Construtor da classe
* @param string $campo : nome do campo file que est enviando o arquivo
move_uploaded_file($_FILES[$campo]['tmp_name'],$arqDestino);
}
}else{
// o PHP nos informa que algum erro ocorreu
$this->Erro = $_FILES[$campo]['error'];
}
}
}
5.5 Classe BD
Essa classe ser responsvel por abstrair o acesso ao banco de dados. Em linhas gerais, ela
centraliza todos os comandos de acesso ao banco de dados. Caso seja necessrio mudar de SGBD a
qualquer momento, s precisamos reescrever essa classe, sem alterar qualquer outro componente da
nossa aplicao.
Arquivo: helpers/class.BD.inc.php
<?php
class BD
{
public $Servidor;
public $Usuario;
public $Link;
public $Banco;
public $Charset;
$this->Servidor = $servidor;
$this->Usuario = $usuario;
$this->Banco = $banco;
$this->Charset = $charset;
class Consulta
{
public $resultado;
public $BD;
if(!$bd->Link)
{
$bd->Abrir();
die("entrou");
}
$this->resultado = mysql_query($sql, $bd->Link);
if($this->resultado)
{
// comando executado com sucesso
}else{
die( "Erro ao executar comando $sql<br />"
.mysql_error());
}
$this->BD = $bd;
}
// retorna a quantidade de registros resultante do
// comando SQL
public function Linhas()
{
return mysql_num_rows($this->resultado);
}
// retorna um valor de um campo especfico
// ex: $obj->Campo(0, 'titulo')
public function Campo($linha, $campo)
Unidade 6
Front Controller
Vamos precisar de um controlador principal que ir inicializar a nossa aplicao. Ele o Front
Controller, que ir centralizar todos os pedidos e requisies feitos a aplicao. Todos os links
devero ser construdos apontando para ele.
Ele ser responsvel por identificar qual controlador dever ser criado e qual o mtodo que dever
ser acionado para cada situao. Para isso ele dever receber, quando necessrio dois parmetros:
controlador : indica o controlador a ser acionado, quando no for informado o
controlador default ser o controlador 'index' que exibir a pgina inicial da
aplicao. Ex: ndex.php?controlador=produto
mtodo : o mtodo do controlador a ser acionado, quando no for informado ser
utilizado o valor default 'index'. Ex.:
ndex.php?controlador=produto&mtodo=listar.
Arquivo: ndex.php
<?php
// classes base
require_once 'system/class.Controller.inc.php';
require_once 'system/class.Model.inc.php';
require_once 'system/class.View.inc.php';
// models
require_once 'app/model/class.LoginModel.inc.php';
require_once 'app/model/class.ProdutoModel.inc.php';
require_once 'app/model/class.FabricanteModel.inc.php';
require_once 'app/model/class.LinhaModel.inc.php';
// controllers
require_once("app/controller/class.IndexController.inc.php");
require_once("app/controller/class.ProdutoController.inc.php");
require_once("app/controller/class.LoginController.inc.php");
// classes obrigatrias
// configurao sistema
require_once 'system/config.inc.php';
if(isset($_REQUEST['metodo']))
{
$metodo = $_REQUEST['metodo'];
}
// Executa o controlador
$controlador = new $classe();
$controlador->$metodo();
Unidade 7
Camada de Apresentao
A camada de visualizao (VIEW) ou apresentao o elemento responsvel pela interao direta
com o usurio final. Neste elemento no h a necessidade do conhecimento de como a informao
foi obtida ou onde ela foi obtida, mas apenas um foco na exibio da mesma.
Nesta camada as interaes com o usurio so disparadas e a comunicao com o modelo ocorre
atravs do monitoramento destes eventos pela camada de controle.
Quando acessamos sistemas via WEB, temos contato direta com esta camada atravs de arquivos
HTML , XML , ASP , PHP, etc. Graas a crescente ascenso deste padro sugiram vrios modelos
que se propuseram a oferecer um facilitador na criao destas camadas.
Dentre estes modelos, que chamamos de Templates, podemos destacar o Template Power e o
Smarty. Vamos utilizar o Template Power por sua simplicidade que ser um facilitador para
compreendermos melhor estes conceitos do MVC. Caso deseje conhecer mais sobre o Template
Power acesse: http://templatepower.codocad.com/ e para obter mais informaes sobre o Smarty
acesse: http://www.smarty.net/
Criaremos aqui uma camada que permita visualizar uma lista de produtos cadastrados em um banco
de dados. No vamos nos deter na sintaxe e semntica da linguagem utilizada em Template Power.
Vamos utilizar os seguintes arquivos:
Arquivo: app/view/master.htm
<html>
<head>
<title>Gerenciamento de Contedo</title>
<link href="css/estilo.css" type="text/css" rel="stylesheet"
/>
<meta http-equiv="Content-Type" content="text/html;
charset=utf-8" />
</head>
<body>
<div id="cabecalho">
<h1> Gerenciamento de Contedo </h1>
</div>
<div id="menu">
<ul>
<!-- START BLOCK : menu-logado -->
</ul>
</div>
<div id="conteudo">
<!-- INCLUDE BLOCK : conteudo -->
</div>
</body>
</html>
<br />
<br />
<br />
<form action="index.php" method="post">
<input type="hidden" name="controlador" value="login" />
<input type="hidden" name="metodo" value="validar" />
<table align="center">
<tr>
<th colspan="2">Acesso Restrito</th>
</tr>
<tr>
<td>Usuario</td>
<td><input type="text" name="usuario" /></td>
</tr>
<tr>
<td>Senha</td>
<td><input type="password" name="senha" /></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="entrar" /></td>
</tr>
</table>
</form>
Arquivo: app/view/bemvindo.htm
<br />
<br />
<br />
<br />
<div id="bemvindo">
<h2>Bem vindo ao administrador de notcias!</h2>
<p>
<small>COPYRIGHT 2011 © Alfamdia</small>
Arquivo: app/view/produto_editar.htm
<form name="frm" method="post" action="index.php"
enctype="multipart/form-data">
<input type="hidden" name="controlador" value="produto" />
<input type="hidden" name="metodo" value="salvar" />
<input type="hidden" name="id" value="{id}" />
<table>
<tr>
<td>Nome</td>
<td>
<input type="text" name="nome" size="50" value="{nome}"
/>
</td>
</tr>
<tr>
<td>Descrio</td>
<td>
<textarea name="descricao" rows="2"
cols="50">{descricao}</textarea>
</td>
</tr>
<tr>
<td>Linha</td>
<td><select name="linha">
<option value="">selecione uma linha</option>
<!-- START BLOCK : item-linha -->
<option value="{id}" {sel}>{nome}</option>
<!-- END BLOCK : item-linha -->
</select>
</td>
</tr>
<tr>
<td>Fabricante</td>
<tr>
<td>Preo</td>
<td>
<input type="text" name="preco" value="{preco}" />
</td>
</tr>
<tr>
<td>Peso</td>
<td>
<input type="text" name="peso" value="{peso}" />
</td>
</tr>
<tr>
<td>Estoque</td>
<td>
<input type="text" name="qtd_estoque"
value="{qtd_estoque}" />
</td>
</tr>
<tr>
<td>Ativo</td>
<td><input type="checkbox" name="ativo" {ativo} /></td>
</tr>
<tr>
<td>Destaque</td>
<td><input type="checkbox" name="destaque" {destaque}
/></td>
</form>
Arquivo: app/view/produto_listar.htm
<a href="index.php?controlador=produto&metodo=editar">Novo
produto</a><br />
Total de produtos cadastrados: {total}<br>
<table width="100%">
<tr>
<th width="60%">Descrio</th>
<th>Preo</th>
<th>Estoque</th>
<th>Aes</th>
</tr>
<!-- START BLOCK : item -->
<tr>
Arquivo: css/estilo.css
* { font-family: "Georgia", serif; }
a {
color: #00f;
text-decoration: none;
}
th {
color: white;
background-color: black;
Unidade 8
Camada de Modelo
O nome Camada lgica da aplicao ou Modelo (Model) deixa bem claro que tratasse do ncleo
do sistema. neste nvel que armazenamos todas as aes que sero realizadas pela aplicao.
Alm disso, aqui tambm fazemos o acesso e manipulao dos dados contidos na base de dados
(persistncia). Estas aes que a camada pode realizar so acionadas atravs da camada de controle,
portanto, aqui apenas estar presente a lgica do negcio.
Com esta separao da regra de negcio das demais camadas, podemos pensar em desenvolver o
sistema independente do mdulo de visualizao. Isto nos permite que o desenvolvimento ocorra de
forma paralela, portanto mais rpida, e ainda nos d a possibilidade de ajustar o layout sem a
necessidade de alterar a regra de negcio da aplicao.
Esta caracterstica de separao do negcio das demais camadas o que chamamos de
encapsulamento de dados, onde temos o comportamento independente da apresentao.
O primeiro arquivo que vamos criar a classe me de todos os modelos de nossa aplicao. Todos
os modelos criados devero extender essa classe.
Arquivo: system/class.Model.inc.php
<?php
if($id>0)
{
$this->CarregarId($id);
}
}
Arquivo: app/model/class.FabricanteModel.inc.php
<?php
class FabricanteModel extends Model
{
public $Id;
public $Nome;
public $TotalLidas;
private $c;
Arquivo: app/model/class.LinhaModel.inc.php
<?php
class LinhaModel extends Model
{
public $Id;
public $Nome;
public $TotalLidas;
private $c;
Arquivo: app/model/class.LoginModel.inc.php
<?php
Arquivo: app/model/class.ProdutoModel.inc.php
<?php
class ProdutoModel extends Model
{
public $Id;
public $Nome;
public $Descricao;
public $Preco;
public $Peso;
public $Destaque;
public $QtdEstoque;
public $Fabricante;
public $Linha;
public $Imagem;
public $Ativo;
public $TotalLidas=0;
private $c;
return true;
}
/**
* Carrega um registro.
* @param int $id Id a ser carregado.
*/
public function CarregarId($id)
{
$id = (int)$id;
if($id>0)
{
$sql = "SELECT * FROM produto WHERE id=$id";
Unidade 9
Camada de Controle
Nesta camada fazemos o controle do fluxo da aplicao, determinando o que deve ser acessado e
exibido. Ela serve como uma camada intermediria entre a camada de apresentao e a lgica.
Teremos aqui um arquivo chamado produtos.controller.php que acionar mtodos e propriedades
contidas nas classes da camada de modelo e por fim enviar uma solicitao de exibio destes
dados para o arquivo de template da camada de viso.
Esta camada nos permite a modificao de forma simples e rpida a sequencia de exibies e
manipulaes que o sistema far. Com isto ganhamos em tempo de implantao, mas
principalmente no processo de manuteno do cdigo.
O primeiro arquivo a ser criado ser a classe me de todos os controladores. Todos os controladores
do nosso sistema devero estender a classe Controller.
Os mtodos implementados iro variar de acordo com as aes que sero disponibilizadas para cada
controlador. O nico mtodo obrigatrio ser o mtodo Index(), que o mtodo default de cada
controlador e ser usado quando nenhum mtodo for informado.
No nosso sistema, tambm faremos uso dos mtodos comuns a todos controladores:
InicializaView() : inicializa a template Power com a Master Page e o arquivo de
include necessrio.
Exibe() : envia a pgina para o usurio.
RestringeAcesso() : quando for acionado, esse mtodo verificar se o usurio se
logou, caso no tenha feito, negar o acesso pgina e encaminhar para a pgina
de login. S ser usado nas pginas em que isso for necessrio.
Arquivo: system/class.Controller.inc.php
<?php
/**
* Classe me para os Controladores.
* Aqui vo as definies comuns a todos os controladores.
* @author Alfamidia
*
*/
class Controller {
/**
* Inicializa a VIEW do Controlador
* @param string $master Nome da Master Page.
* @param string $include Nome do include block se houver.
*/
public function InicializaView($include="",
$master="master.htm") {
$this->tpl = new TemplatePower ( "app/view/$master" );
if ($include != "") {
$this->tpl->assignInclude ( "conteudo",
"app/view/$include" );
}
$this->tpl->prepare();
/**
* Responsvel por exibir a VIEW
*/
public function Exibe() {
$this->tpl->printToScreen ();
/**
* Restringe o acesso, se o usurio no estiver logado
* exibe a tela de login e suspende a execuo do restante
* do programa.
*/
public function RestringeAcesso()
{
if(!isset($_SESSION['logado']))
{
$log = new LoginController();
$log->Index();
exit;
}
}
/**
* Converte um valor no formato '1.234,56' em FLOAT
* @param string $valor
*/
public function ConverteParaFloat($valor)
{
// supondo que a entrada seja 3.400,25
// remove o ponto => 3400,25
$nro = str_replace('.', '', $valor);
// troca a virgula por ponto => 3400.25
$nro = str_replace(',', '.', $nro);
// converte para float
$nro = (float)$valor;
return $nro;
}
/**
Arquivo: app/controller/class.IndexController.inc.php
<?php
}
}
Arquivo: app/controller/class.LoginController.inc.php
<?php
class LoginController extends Controller
{
public function Index()
{
$this->InicializaView('login_form.htm');
$this->Exibe();
}
$this->InicializaView('bemvindo.htm');
$this->Exibe();
}
Arquivo: app/controller/class.ProdutoController.inc.php
<?php
$this->InicializaView("produto_listar.htm");
$this->tpl->assign("total", $pro->TotalLidas);
for($i=0; $i<$pro->TotalLidas; $i++)
{
$pro->Ler($i);
$this->tpl->newBlock("item");
$this->tpl->assign("id", $pro->Id);
$this->tpl->assign("nome", $pro->Nome);
if($pro->TotalLidas==0)
{
$this->tpl->newBlock("semregistros");
}
$this->Exibe();
}
$this->InicializaView("produto_editar.htm");
// inicializa
$fabId = 0;
$linId = 0;
if($pro->Imagem!="")
{
$this->tpl->newBlock('imagem');
$this->tpl->assign('imagem', $pro->Imagem);
}
}
// preenche selects
$fab = new FabricanteModel();
$fab->CarregarTodas();
for($i=0; $i<$fab->TotalLidas; $i++)
{
$fab->Ler($i);
$this->tpl->newBlock('item-fabricante');
$this->tpl->assign('id', $fab->Id);
$this->tpl->assign('nome', $fab->Nome);
// se for edio, marca o item selecionado
if($fab->Id==$fabId) $this->tpl->assign('sel',
'selected');
}
// preenche selects
$lin = new LinhaModel();
$lin->CarregarTodas();
for($i=0; $i<$lin->TotalLidas; $i++)
{
$lin->Ler($i);
$this->tpl->newBlock('item-linha');
$this->tpl->assign('id', $lin->Id);
$this->Exibe();
}
if(isset($_POST['bt_salvar']))
{
$id = (int)$_POST['id'];
$mod->Salvar();
}
$this->Listar();
}
if(isset($_GET['id']))
{
$id = (int)$_GET['id'];
$mod = new ProdutoModel($id);
$mod->Excluir();
$this->Listar();
}
}
}