Vous êtes sur la page 1sur 33

Implementação de Software em MVC

Padrão de Arquitetura de Software MVC


Segundo Wikipédia (2015), o padrão de arquitetura de software Model-View-
Controller, mais conhecido como MVC, tem como objetivo separar a estrutura do
software em camadas.
A separação é feita visando a reutilização de códigos e a separação dos conceitos, e
com isso, tornar a estrutura do software flexível e de fácil manutenção.
As camadas do MVC são divididas da seguinte forma:
• Modelo (model): é responsável por manipular os dados da aplicação, as regras de
negócio, a lógica e as funções. As validações dos dados antes de serem persistidos
também podem ser adicionados nessa camada, dependendo da implementação.
• Visão (view): é representada pela interface com o usuário, onde ele pode interagir
com a aplicação. Essa camada poderá enviar dados para o controlador e requisitar
dados do modelo.
• Controle (controller): faz a comunicação entre a camada visão e a camada modelo.
As solicitações vindas da camada visão são preparadas e enviadas para a camada
modelo.
A seguir, a Figura 1 demonstra como funciona as interações entre as camadas do
padrão MVC:

O padrão MVC foi desenvolvido para aplicações desktop, posteriormente, foi adaptado
para aplicações web. Atualmente, existem vários frameworks que utilizam esse padrão
para dividir o código em camadas. A forma de dividir as camadas pode variar de acordo
com implementação de cada framework. O MVC não é um padrão exclusivo da
Linguagem PHP, pelo contrário, ele está presente em praticamente todas as linguagens
de programação.
Outro ponto importante é entender como funciona o seu fluxo de interações. O ciclo
de interações inicia-se por meio de uma requisição feita pelo usuário, por exemplo, o
usuário clica em um botão que faz uma chamada no servidor, o controlador recebe
uma solicitação contendo informações enviadas pela camada visão; se for necessário,
o controlador solicita uma ação para a camada modelo e, em seguida, retorna o
resultado do processamento para a visão, permitindo ao usuário visualizar o resultado
de sua requisição. O modelo e o controlador não precisam conhecer a implementação
de código que está na visão, mas a visão precisa conhecer os dois.
Analisando o fluxo de interação do padrão MVC, chegamos a uma conclusão: se a
camada de controle (controller) e de modelo (model) não precisam conhecer a camada
de visão (view), então é porque elas não são dependentes da camada de visão, ou seja,
se futuramente for preciso reformular o layout do sistema ou até mesmo modificá-lo,
isso poderá ser feito sem alterar os códigos implementados nas camadas de modelo e
de controle; assim, a lógica de negócio e o controle das informações permanecerão
intactos.

Frameworks
De acordo com Wikipédia (2015), o framework é um conjunto de códigos pré-
programados com o intuito de prover uma funcionalidade genérica entre vários
projetos de softwares.
Geralmente, os frameworks permitem um alto grau de customização, de maneira que
possam atender às especificidades de cada aplicação. Um framework não pode ser
caracterizado como uma biblioteca adicional, porque, diferentemente das bibliotecas,
ele controla o fluxo de controle da aplicação, chamado de Inversão de Controle.
Em outras palavras, um framework é uma estrutura de pastas e arquivos, geralmente
no padrão MVC, contendo várias rotinas de códigos pré-programados. Ao invés de
você criar a estrutura de códigos do seu projeto, você escolhe o framework de sua
preferência, faz o download e inicia o seu projeto dentro da estrutura do framework.
A vantagem de fazer isso é que a maioria dos frameworks foram criados por grupos de
grandes desenvolvedores; por isso, as camadas de modelos e controladores possuem
inúmeros recursos para facilitar o desenvolvimento, além de fornecer todo o suporte
necessário no quesito de segurança, pois a maioria dos frameworks aplicam
tratamentos de segurança por padrão, como, por exemplo, a prevenção de ataques
contra SQL Injection.
Os problemas mais comuns de segurança, tratamento de erros, controle de sessão de
usuários, enfim, essa parte comum entre todos os sistemas já estão implementadas
dentro do framework; você só precisa chamar os métodos necessários para eles
funcionarem.
Para a Linguagem PHP, existem vários frameworks conceituados no mercado, entre
eles estão o Laravel, Symfony2, CakePHP, Zend e CodeIgniter. Segundo dados do
SitePoint (2016), o Laravel é o framework PHP mais popular no mundo. Seu diferencial
tem sido a facilidade de uso e a excelente documentação disponível para os
desenvolvedores.
Na hora de escolher um framework para o seu projeto, um fator decisivo deve ser a
sua documentação, pois isso fará muita diferença no decorrer do desenvolvimento do
projeto; um framework muda o estilo de programação do projeto e o torna totalmente
dependente.
Escolher um framework sem documentação é o mesmo que você adquirir um carro
sem saber dirigir e ainda não ter um instrutor para ensiná-lo.
Implementando MVC em PHP
Agora que você já sabe o que é o padrão MVC e um framework, criaremos um projeto
e implementaremos uma estrutura semelhante a um framework que utiliza esse
padrão. É claro que, ao invés de criar nossa própria estrutura, poderíamos utilizar um
framework existente, já que essa seria a escolha mais sensata. Mas não faremos isso
por dois motivos:
• Primeiro: seria necessária uma obra inteira para conceituar toda a complexidade de
um framework.
• Segundo: esse modelo que criaremos ilustrará de forma sucinta como um framework
trabalha, e é imprescindível entendermos isso antes de utilizar qualquer framework.
Bom, vamos iniciar a criação do nosso projeto. Para isso, realize os passos a seguir:
• Crie uma pasta chamada locadora dentro pasta htdocs do XAMP, localizada em: C:\
xampp\htdocs\.
• Dentro da pasta locadora, crie uma estrutura de pastas e arquivos de acordo com a
ilustração a seguir:
│ .htaccess
│ config.php
│ index.php

|-─Classes
│ Controller.php
© Projeto de Software com Banco de Dados 71
UNIDADE 3 – Implemen tação do Pad rão MVC
│ Model.php

|-─Controllers
│ HomeController.php
│ ClientesController.php

|-─Models
│ ClienteModel.php

|-─Views
│ |-─home
│ │ index.php
││
│ |-─clientes
│ │ index.php
│ │ formulario.php
││
│ |-─erros
│ │ 404.php
││
│ |-─layout
│ │ |-─css
│ │ |-─js
│ │ └─images
││
│ └─includes
│ cabecalho.inc.php
│ rodape.inc.php

└──────────────

Olhando para essa estrutura, você deve estar se perguntando se realmente precisa de
tudo isso. E a resposta é sim. Conforme citado anteriormente, essa estrutura é um
“resumo” da estrutura de um framework. Embora não pareça, faremos uma
implementação simples; toda essa estrutura é para reduzir códigos no
desenvolvimento do sistema.
Não se preocupe, no final desta unidade, será disponibilizado um link no qual você
poderá fazer o download dessa estrutura montada, mas, antes disso, você precisa
tentar montá-la para entender como funciona.
Ao criar a estrutura, você deverá tomar muito cuidado na hora de nomear os arquivos,
todos os nomes devem seguir rigorosamente o padrão estabelecido anteriormente,
inclusive as letras maiúsculas e minúsculas. As pastas Classes, Models, Controllers e
Views devem ser nomeadas no plural e com a primeira letra maiúscula.
Para entendê-la melhor, a seguir, veremos a documentação dessa divisão de pastas e
arquivos e suas respectivas implementações.

htaccess: esse arquivo é responsável por redirecionar todas as requisições para o


arquivo index.php; dessa forma, você não precisará informar o formato do arquivo
(.php) na URL.

Início Código 1––––––––––––––––––––––––––––––––––––––––––––––––––––––––––


RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.+)$ index.php?route=$1 [QSA,L]
Fim Código 1–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

config.php: nesse arquivo ficará as configurações básicas da aplicação, como os dados


de conexão com o banco de dados, caminho da pasta de uploads etc.
Início Código 2––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
<?php
/*
*/
/* Caminho raiz do servidor */
define( ‘ABSPATH’, realpath( dirname( __FILE__ ) ) . DIRECTORY_SEPARATOR
);
/* Caminho da home */
define( ‘HOME_URL’, dirname( $_SERVER[‘PHP_SELF’] ) . DIRECTORY_SEPARATOR
);
/* Endereço do servidor de banco de dados */
define( ‘HOST’, ‘localhost’ );
/* Usuário do banco de dados */
define( ‘USUARIO’, ‘default’ );
/* Senha do banco de dados */
define( ‘SENHA’, ‘default’ );
/* Nome do banco de dados */
define( ‘BANCO_DE_DADOS’, ‘locadora’ );
/* Se você estiver desenvolvendo, modifique o valor para true */
define( ‘DEBUG’, true );
Fim Código 2–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

index.php: todas as requisições serão redirecionadas para esse arquivo; portanto,


ele será responsável por incluir os arquivos de modelos, visões e controladores.
Início Código 3–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
<?php
/* Incluir arquivo de conexão */
require_once ‘config.php’;
// Inicia a sessão
session_start();
// Verifica o modo depurador está ativo
if ( ! defined( ‘DEBUG’ ) || DEBUG === false ) {
// Esconde todos os erros
error_reporting( 0 );
ini_set( “display_errors”, 0 );
}
else {
// Mostra todos os erros
error_reporting( E_ALL );
ini_set( “display_errors”, 1 );
}
/*
* Função nativa do PHP para incluir arquivos de classes automaticamente
*/
function __autoload( $nome_da_classe ) {
// Pegar caminho do arquivo a ser incluido
$arquivo = ABSPATH . str_replace( ‘\\’, DIRECTORY_SEPARATOR, $nome_
da_classe ) . ‘.php’;
// Verificar se o arquivo existe
if ( is_file( $arquivo ) ) {
require_once $arquivo;
}
}
// Retorna a posição de um vetor se ela existir
function array_get( $array, $key ) {
// Verifica se a chave existe no array
if ( isset( $array[$key] ) && ! empty( $array[$key] ) ) {
// Retorna o valor da chave
return $array[$key];
}
// Retorna nulo por padrão
return null;
}
global $controlador, $acao, $parametros;
// Verifica se o parâmetro path foi enviado
if ( isset( $_GET[‘route’] ) ) {
// Captura o valor de $_GET[‘path’]
$route = $_GET[‘route’];
// Limpa os dados
$route = rtrim( $route, ‘/’ );
$route = filter_var( $route, FILTER_SANITIZE_URL );
// Cria um array de parâmetros
$route = explode( ‘/’, $route );
// Configura as propriedades
$controlador = ucfirst( array_get( $route, 0 ) );
$controlador .= ‘Controller’;
$acao = array_get( $route, 1 );
// Configura os parâmetros
if ( array_get( $route, 2 ) ) {
unset( $route[0] );
unset( $route[1] );
// Os parâmetros sempre virão após a ação
$parametros = array_values( $route );
}
}
/**
* Se nenhum controlador for requisitado,
* será chamado a ação padrão $home_controller->index()
*/
if ( ! $controlador ) {
// Adiciona o controlador padrão
require_once ABSPATH . ‘Controllers/HomeController.php’;
// Instancia o controlador padrão
$controlador = new Controllers\HomeController();
// Executa o método index()
$controlador->index();
// Parar a execução aqui
return;
}
// Se o arquivo do controlador não existir, não faremos nada
if ( ! file_exists( ABSPATH . ‘Controllers/’ . $controlador . ‘.php’ ) ) {
// Página não encontrada
require_once ABSPATH . ‘Views/erros/404.php’;
// Parar a execução aqui
return;
}
// Inclui o arquivo do controlador
require_once ABSPATH . ‘Controllers/’ . $controlador . ‘.php’;
// Adicionar caminho da namespace no controlador
$controlador_namespace = “Controllers\\{$controlador}”;
// Cria o objeto da classe do controlador e envia os parâmetros
$controlador = new $controlador_namespace( $parametros );
// Se o método indicado existir, executa o método e envia os parâmetros
if ( method_exists( $controlador, $acao ) ) {
$controlador->{$acao}( $parametros );
// Parar a execução aqui
return;
}
// Sem ação, executará o método index
if ( ! $acao && method_exists( $controlador, ‘index’ ) ) {
$controlador->index( $parametros );
// Parar a execução aqui
return;
}
// Página não encontrada
require_once ABSPATH . ‘Views/erros/404.php’;
// Parar a execução aqui
return;
Fim Código 3––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

Classes/Controller.php: esse arquivo conterá a implementação básica dos


controladores;
assim, todos os controladores deverão estendê-lo.
Início Código 4–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
<?php
/**
* Controlador genérico
*/
namespace Classes;
class Controller {
// Parametros via url
protected $parametros;
// Método construtor da classe
public function __construct( $parametros = array() ) {
}
}
Fim Código 4––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
Classes/Model.php: esse arquivo conterá a implementação básica dos modelos,
bem como o algoritmo de conexão com o Banco de Dados MySQL utilizando o driver
MySQLi orientado a objetos.
Início Código 5–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
<?php
/**
* Modelo genérico
*/
namespace Classes;
class Model {
// Conexão com o banco de dados
public static $mysqli = false;
// Cópia da instancia do mysqli
protected $db = false;
// Método construtor da classe
public function __construct() {
// Verificar se já tem uma conexão aberta
if ( Model::$mysqli === false ) {
// Conectar no banco de dados
Model::$mysqli = new \mysqli(
HOST,
USUARIO,
SENHA,
BANCO_DE_DADOS
);
// Verificar se ocorreu erro na conexão
if ( Model::$mysqli->connect_errno ) {
die( ‘Falha na conexão com o MySQL: ‘ . Model::$mysqli
->connect_error );
}
}
// Utilizar conexão aberta
$this->db = Model::$mysqli;
}
}
Fim Código 5––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

Controllers: todos os controladores serão colocados dentro dessa pasta, a


nomenclatura
deverá seguir o padrão ClientesController.php, sendo a palavra Controller.
php precedida do nome do controlador no plural com a primeira letra maiúscula.

Controllers/HomeController.php: esse arquivo será o controlador da home do nosso


projeto, sua existência é obrigatória; assim, você não deve excluí-lo e nem renomeá-
lo, mas, se precisar fazer isso, você deverá mudar algumas linhas no arquivo
index.php.
Início Código 6–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
<?php
/**
* Controlador Home
*/
namespace Controllers;
use Classes\Controller;
class HomeController extends Controller {
// URL /
public function index() {
// Incluir o layout da ação
require_once ABSPATH . ‘Views/home/index.php’;
}
}
Fim Código 6––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

Controllers/ClientesController.php: esse arquivo serve como exemplo de


implementação
de um controlador.
Início Código 7–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
<?php
/**
* Controlador Clientes
*/
namespace Controllers;
use Classes\Controller;
class ClientesController extends Controller {
// URL /clientes
public function index() {
// Incluir o layout da ação
require_once ABSPATH . ‘Views/clientes/index.php’;
}
// URL /clientes/form
public function form() {
// Incluir o layout da ação
require_once ABSPATH . ‘Views/clientes/form.php’;
}
}
Fim Código 7––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
Models: todos os modelos serão colocados dentro dessa pasta, e a nomenclatura
deverá seguir o padrão ClienteModel.php, sendo a palavra Model.php precedida do
nome do modelo no singular com a primeira letra maiúscula.
10) Models/ClienteModel.php: esse arquivo serve como exemplo de implementação
de um modelo.
Início Código 8–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
<?php
/**
* Modelo de dados de Clientes
*/
namespace Models;
use Classes\Model;
class ClienteModel extends Model {
/*
* Buscar cliente pelo ID
*/
public function filtrar_por_id( $id ) {
}
/*
* Buscar todos os clientes
*/
public function filtrar_todos() {
}
/*
* Salvar registro
*/
public function salvar( $cliente ) {
}
/*
* Inserir novo registro via INSERT INTO...
*/
public function inserir( $cliente ) {
}
/*
* Alterar registro via UPDATE
*/
public function alterar( $cliente ) {
}
/*
* Excluir registro
*/
public function excluir( $id ) {
}
}
Fim Código 8––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
Views: dentro dessa pasta você tem a liberdade de criar o seu próprio padrão, porém,
recomendamos que siga a ilustração anterior. Dentro dela ficarão todos os arquivos
relacionados ao layout do sistema, bem como os arquivos .CSS, .JS e .PHP
contendo os códigos html de todas as páginas do sistema.

Views/home/index.php: nesse arquivo ficará o layout da home do nosso projeto.


Início Código 9–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
<?php require_once ABSPATH . ‘Views/includes/cabecalho.inc.php’; ?>
<div class=”jumbotron”>
<h1 style=”margin-top: 0;”>Seja bem-vindo(a)</h1>
<p>
Este é um projeto de software para locadora de filmes conectado
ao banco de dados MySQL.
O objetivo deste projeto é apresentar um modelo MVC de aplicação
criado em PHP.
</p>
</div>
<?php require_once ABSPATH . ‘Views/includes/rodape.inc.php’; ?>
Fim Código 9––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

Views/clientes/index.php: nesse arquivo ficará o layout da página que lista todos os


clientes cadastrados.
Início Código 10––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
<?php require_once ABSPATH . ‘Views/includes/cabecalho.inc.php’; ?>
<div class=”alert alert-info”>

Esta página está chamando a ação ClientesController::Index


</div>
<?php require_once ABSPATH . ‘Views/includes/rodape.inc.php’; ?>
Fim Código 10–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

Views/clientes/form.php: neste arquivo ficará o layout da página de formulário de


cadastro
de clientes.
Início Código 11––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
<?php require_once ABSPATH . ‘Views/includes/cabecalho.inc.php’; ?>
<div class=”alert alert-info”>
Esta página está chamando a ação ClientesController::Form
</div>
<?php require_once ABSPATH . ‘Views/includes/rodape.inc.php’; ?>
Fim Código 11–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

Views/erros/404.php: quando o usuário digitar um link inexistente, automaticamente


será carregado o conteúdo dessa página. A implementação que faz essa chamada
está no arquivo index.php.
Início Código 12––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
<?php require_once ABSPATH . ‘Views/includes/cabecalho.inc.php’; ?>
<br>
<div class=”alert alert-danger”>Página não encontrada!</div>
<?php require_once ABSPATH . ‘Views/includes/rodape.inc.php’; ?>
Fim Código 12–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

Como você pôde ver, a implementação de códigos mais complexa da nossa estrutura
está no arquivo index.php, porque esse arquivo receberá todas as requisições do
sistema e repassará para os arquivos responsáveis por processar e responder as
requisições. Por exemplo, isso acontecerá quando você requisitar as seguintes URLs
através do seu navegador de internet: <http://localhost/locadora/clientes> ou
<http://localhost/locadora/clientes/index>.
No arquivo index.php será executado o seguinte código:
Início Código 13––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
// Instancia o controlador ClientesController
$controlador = new ClientesController();
// Executa o método index()
$controlador->index();
Fim Código 13–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

Se você quiser que o método formulario() do controlador Clientes seja executado,


basta
você digitar o seguinte endereço: <http://localhost/locadora/clientes/formulario>. O
código
executado será o seguinte:
Início Código 14––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
// Instancia o controlador ClientesController
$controlador = new ClientesController();
// Executa o método formulario ()
$controlador->formulario();
Fim Código 14–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

Ou seja, o arquivo index.php está programado para entender a URL da seguinte forma:
<http://localhost/locadora/[CONTROLADOR]/[ACAO]>.
Se, por ventura, você chamar um controlador ou uma ação que não existe, o arquivo
Views/erros/404.php será chamado e o usuário visualizará a mensagem de página não
encontrada.
A grande vantagem dessa estrutura é a mesma do framework. Você não precisa
entender toda a implementação feita nos arquivos index.php, Classes/Model.php e
Classes/Controller.
php, você só precisa saber quais métodos são fornecidos por eles e como você tem de
chamá-los.
Como fazer o download da estrutura do projeto
Você poderá fazer o download desse projeto completo por meio do seguinte link:
<https://github.com/eduardoazevedo3/projeto-de-software-php>. A maior parte dos
códigos está comentada; dessa forma, você poderá compreender melhor o
funcionamento de cada recurso.
A implementação
Utilizando o modelo desenvolvido na unidade anterior, nesta unidade,
desenvolveremos as páginas: Cadastro de Clientes, Filmes e Categorias de Filmes e
deixaremos a estrutura pronta para implementar a página de Locações de Filmes.
Esse modelo de projeto foi criado para atender às necessidades básicas de um sistema
por meio de uma implementação genérica nas camadas de modelo de dados e
controlador. Graças à estrutura que adotamos, você poderá realizar novas
implementações nativas, como módulo de cache, autenticação, controle de sessão,
logs de erros, ORM etc.

Modelos
Os modelos do nosso projeto estão estendendo as funcionalidades do arquivo Classes/
Model.php. Nesse arquivo, implementamos a conexão com o banco de dados por
meio do driver MySQLi do PHP. Essa implementação foi feita de maneira otimizada, na
qual o algoritmo de conexão detecta se já existe alguma conexão em aberto, se existir,
ele utiliza a conexão existente, se não, ele cria uma nova conexão com o MySQL.
Esse tipo de implementação é muito importante, pois conectar e desconectar a cada
comando SQL pode tornar a aplicação lenta, além de consumir mais recursos de
hardware do servidor.
Na unidade anterior, criamos a estrutura de arquivos, classes e métodos dos modelos;
nesta unidade, implementaremos os métodos para executar comandos SQL no banco
de dados, assim será possível filtrar, inserir, alterar e excluir dados no banco de dados
por meio das nossas classes de modelos.

• Models/ClienteModel.php: arquivo responsável por manipular a tabela de Clientes


no banco de dados.

<?php
/**
* Modelo de dados de Clientes
*/
namespace Models;
use Classes\Model;
class ClienteModel extends Model {
/*
* Buscar cliente pelo ID
*/
public function filtrar_por_id( $id ) {
// Prepare SQL para receber parametros
$stmt = $this->db->prepare(
‘SELECT * FROM clientes
WHERE id = ?’
);
// Proteger contra SQL Injection
$stmt->bind_param( ‘i’, $id );
// Executar comando SQL e retorna resultado
$stmt->execute();
// Returnar um registro, se encontrar
return $stmt->get_result()->fetch_object();
}
/*
* Buscar todas as clientes
*/
public function filtrar_todos() {
// Prepare SQL para receber parametros
$stmt = $this->db->prepare(
‘SELECT * FROM clientes’
);
// Executar comando SQL e retorna resultado
$stmt->execute();
// Returna resultado
return $stmt->get_result();
}
/*
* Salvar registro
* detecta se deve executar um INSERT ou UPDATE
*/
public function salvar( $cliente ) {
if ( $cliente->id == NULL || empty( $cliente->id ) ) {
$this->inserir( $cliente );
} else {
$this->alterar( $cliente );
}
}
/*
* Inserir novo registro via INSERT INTO...
*/
public function inserir( $cliente ) {
// Prepare SQL para receber parametros
$stmt = $this->db->prepare(
‘INSERT INTO clientes (cpf, nome, cep, endereco, numero,
bairro, cidade, uf, telefone, email)
VALUES (?,?,?,?,?,?,?,?,?,?)’
);
// Proteger contra SQL Injection
$stmt->bind_param( ‘ssssssssss’,
$cliente->cpf,
$cliente->nome,
$cliente->cep,
$cliente->endereco,
$cliente->numero,
$cliente->bairro,
$cliente->cidade,
$cliente->uf,
$cliente->telefone,
$cliente->email
);
// Executar comando SQL
return $stmt->execute();
}
/*
* Alterar registro via UPDATE
*/
public function alterar( $cliente ) {
// Prepare SQL para receber parametros
$stmt = $this->db->prepare(
‘UPDATE clientes
SET cpf = ?,
nome = ?,
cep = ?,
endereco = ?,
numero = ?,
bairro = ?,
cidade = ?,
uf = ?,
telefone = ?,
email = ?
WHERE id = ?’
);
// Proteger contra SQL Injection
$stmt->bind_param( ‘ssssssssssi’,
$cliente->cpf,
$cliente->nome,
$cliente->cep,
$cliente->endereco,
$cliente->numero,
$cliente->bairro,
$cliente->cidade,
$cliente->uf,
$cliente->telefone,
$cliente->email,
$cliente->id
);
// Executar comando SQL
return $stmt->execute();
}
/*
* Excluir registro
*/
public function excluir( $id ) {
// Prepare SQL para receber parametros
$stmt = $this->db->prepare(
‘DELETE FROM clientes
WHERE id = ?’
);
// Proteger contra SQL Injection
$stmt->bind_param( ‘i’, $id );
// Executar comando SQL
return $stmt->execute();
}
}

• Models/CategoriaModel.php: arquivo responsável por manipular a tabela de


Categoria de Filmes no banco de dados.
<?php
/**
* Modelo de dados de Categorias
*/
namespace Models;
use Classes\Model;
class CategoriaModel extends Model {
/*
* Buscar categoria pelo ID
*/
public function filtrar_por_id( $id ) {
// Prepare SQL para receber parametros
$stmt = $this->db->prepare(
‘SELECT * FROM categorias
WHERE id = ?’
);
// Proteger contra SQL Injection
$stmt->bind_param( ‘i’, $id );
// Executar comando SQL e retorna resultado
$stmt->execute();
// Returnar um registro, se encontrar
return $stmt->get_result()->fetch_object();
}
/*
* Buscar todas as categorias
*/
public function filtrar_todos() {
// Prepare SQL para receber parametros
$stmt = $this->db->prepare(
‘SELECT * FROM categorias’
);
// Executar comando SQL e retorna resultado
$stmt->execute();
// Returna resultado
return $stmt->get_result();
}
/*
* Salvar registro
* detecta se deve executar um INSERT ou UPDATE
*/
public function salvar( $categoria ) {
if ( $categoria->id == NULL || empty( $categoria->id ) ) {
$this->inserir( $categoria );
} else {
$this->alterar( $categoria );
}
}
/*
* Inserir novo registro via INSERT INTO...
*/
public function inserir( $categoria ) {
// Prepare SQL para receber parametros
$stmt = $this->db->prepare(
‘INSERT INTO categorias (descricao)
VALUES (?)’
);
// Proteger contra SQL Injection
$stmt->bind_param( ‘s’, $categoria->descricao );
// Executar comando SQL
return $stmt->execute();
}
/*
* Alterar registro via UPDATE
*/
public function alterar( $categoria ) {
// Prepare SQL para receber parametros
$stmt = $this->db->prepare(
‘UPDATE categorias
SET descricao = ?
WHERE id = ?’
);
// Proteger contra SQL Injection
$stmt->bind_param( ‘si’,
$categoria->descricao,
$categoria->id
);
// Executar comando SQL
return $stmt->execute();
}
/*
* Excluir registro
*/
public function excluir( $id ) {
// Prepare SQL para receber parametros
$stmt = $this->db->prepare(
‘DELETE FROM categorias
WHERE id = ?’
);
// Proteger contra SQL Injection
$stmt->bind_param( ‘i’, $id );
// Executar comando SQL
return $stmt->execute();
}
}

• Models/FilmeModel.php: arquivo responsável por manipular a tabela de Filmes


no banco de dados.
<?php
/**
* Modelo de dados de Filmes
*/
namespace Models;
use Classes\Model;
class FilmeModel extends Model {
/*
* Buscar filme pelo ID
*/
public function filtrar_por_id( $id ) {
// Prepare SQL para receber parametros
$stmt = $this->db->prepare(
‘SELECT * FROM filmes
WHERE id = ?’
);
// Proteger contra SQL Injection
$stmt->bind_param( ‘i’, $id );
// Executar comando SQL e retorna resultado
$stmt->execute();
// Returnar um registro, se encontrar
return $stmt->get_result()->fetch_object();
}
/*
* Buscar todas as filmes
*/
public function filtrar_todos() {
// Prepare SQL para receber parametros
$stmt = $this->db->prepare(
‘SELECT categorias.descricao AS categoria,
filmes.*
FROM filmes
JOIN categorias
ON categorias.id = filmes.categoria_id’
);
// Executar comando SQL e retorna resultado
$stmt->execute();
// Returna resultado
return $stmt->get_result();
}
/*
* Salvar registro
* detecta se deve executar um INSERT ou UPDATE
*/
public function salvar( $filme ) {
if ( $filme->id == NULL || empty( $filme->id ) ) {
$this->inserir( $filme );
} else {
$this->alterar( $filme );
}
}
/*
* Inserir novo registro via INSERT INTO...
*/
public function inserir( $filme ) {
// Prepare SQL para receber parametros
$stmt = $this->db->prepare(
‘INSERT INTO filmes (categoria_id, titulo)
VALUES (?,?)’
);
// Proteger contra SQL Injection
$stmt->bind_param( ‘ss’,
$filme->categoria_id,
$filme->titulo
);
// Executar comando SQL
return $stmt->execute();
}
/*
* Alterar registro via UPDATE
*/
public function alterar( $filme ) {
// Prepare SQL para receber parametros
$stmt = $this->db->prepare(
‘UPDATE filmes
SET categoria_id = ?,
titulo = ?
WHERE id = ?’
);
// Proteger contra SQL Injection
$stmt->bind_param( ‘ssi’,
$filme->categoria_id,
$filme->titulo,
$filme->id
);
// Executar comando SQL
return $stmt->execute();
}
/*
* Excluir registro
*/
public function excluir( $id ) {
// Prepare SQL para receber parametros
$stmt = $this->db->prepare(
‘DELETE FROM filmes
WHERE id = ?’
);
// Proteger contra SQL Injection
$stmt->bind_param( ‘i’, $id );
// Executar comando SQL
return $stmt->execute();
}
}

Como você pôde ver, as implementações dos modelos são praticamente iguais, a
diferença está no nome das tabelas e das colunas nos comandos SQL, e também nos
parâmetros enviados para a função prepare() do driver MySQLi.
Outro detalhe importante, são os tipos de dados retornados pelos métodos que
realizam consultas no banco de dados. O método filtrar_todos() está retornando um
objeto do mysqli_result, sendo assim, será necessário compreender o funcionamento
do driver do mysqli para percorrer os dados retornados e colocá-los em tela para o
usuário por meio da camada de visão.

Para compreender melhor o funcionamento da classe MySQLi_Result, acesse o seguinte link:


<http://php.net/manual/pt_BR/class.mysqli-result.php>.

Neste momento, temos toda a implementação necessária para programar as


funcionalidades básicas dos cadastros de clientes, filmes e categoria de filmes.
2.3. Controladores Os controladores serão instanciados e seus métodos serão
invocados de acordo com as requisições recebidas via URL. Conforme estudamos na
unidade anterior, a chamada dos métodos será realizada de acordo com o seguinte
padrão: <http://localhost/locadora/[CONTROLADOR]/[ACAO].
As ações referem-se aos métodos declarados nos controladores, ou seja, se você
chamar a URL: <http://localhost/locadora/clientes/form>, será invocado o método
form() dentro de Controlador Clientes.

// URL /clientes/form
public function form() {
// Incluir o layout da ação
require_once ABSPATH . ‘Views/clientes/form.php’;
}

Esse método está carregando a implementação do arquivo Views/clientes/form.php.


No caso, ainda não desenhamos o formulário Cadastro de Clientes, no entanto,
carregará o seguinte conteúdo:
<?php require_once ABSPATH . ‘Views/includes/cabecalho.inc.php’; ?>
<div class=”alert alert-info”>
Esta página está chamando a ação ClientesController::Form
</div>
<?php require_once ABSPATH . ‘Views/includes/rodape.inc.php’; ?>

No padrão MVC, os controladores têm a função de intermediar a comunicação entre


as camadas de visão (view) e de modelo (model), portanto, os dados enviados pelo
usuário por meio da camada de visão serão preparados e depois enviados para o
modelo; dessa forma, é possível garantir a consistência dos dados por meio de um
recurso de validação implementado no controlador.
Para consultar os dados, a camada de visão terá acesso direto ao modelo, mas, sempre
que possível, é recomendado que essa camada receba os dados do controlador, assim,
você poderá prepará-los para serem apresentados em tela, como, por exemplo,
formatar datas, valores monetários etc.
A seguir, veja como seria a implementação do controlador buscando todos os clientes
e enviando para a camada visão.

• Método index() do controlador de clientes:

// URL /clientes
public function index() {
// Buscar todos os clientes da tabela de clientes
$clientes = $this->cliente_model->filtrar_todos();
// Incluir o layout da ação
require_once ABSPATH . ‘Views/clientes/index.php’;
}

• Implementação da camada de visão que listará todos os clientes dentro de uma


tabela:
<?php require_once ABSPATH . ‘Views/includes/cabecalho.inc.php’; ?>
<table class=”table table-striped table-hover”>
<thead>
<tr>
<th>#</th>
<th>Nome</th>
<th>CPF</th>
<th>E-mail</th>
</tr>
</thead>
<tbody>
<?php while ( $cliente = $clientes->fetch_object() ) : ?>
<tr>
<td><?php echo $cliente->id ?></td>
<td><?php echo $cliente->nome ?></td>
<td><?php echo $cliente->cpf ?></td>
<td><?php echo $cliente->email ?></td>
</tr>
<?php endwhile; ?>
</tbody>
</table>
<?php require_once ABSPATH . ‘Views/includes/rodape.inc.php’; ?>

No controlador, a variável $clientes está recebendo todos os clientes cadastrados por


meio do método filtrar_todos() que foi declarado no arquivo ClienteModel.php. Como
a camada de visão está sendo incluída dentro do mesmo método da variável $clientes,
então a visão terá acesso aos clientes armazenados nessa variável, dessa forma, os
clientes poderão ser descarregados dentro da tabela em HTML.
Outro exemplo seria a camada de visão solicitando uma transação: salvar um novo
cliente.
Nesse caso, a solicitação deverá obrigatoriamente passar pelo controlador, porque a
visão não pode executar transações direto no modelo, pois é necessário o controlador
converter os dados recebidos para o formato de leitura do modelo e depois solicitar a
transação. Embora não seja recomendado fazer isso, mas o desenvolvedor pode forçar
as execuções de transações diretas da visão para o modelo, porém, isso quebraria as
regras do padrão MVC, tornando a aplicação dependente da camada de visão.
Geralmente, as transações são solicitadas pelo usuário do sistema por meio de um
formulário;
por exemplo:

• O usuário preenche um formulário de cadastro com os dados de um cliente e clica no


botão salvar.
• Os dados são enviados para o método salvar() do controlador de clientes através da
URL: <http://localhost/locadora/clientes/salvar>.
• Os dados chegarão com o tipo array() do PHP, então eles são convertidos em objeto
e passados como parâmetro no método salvar() do modelo de clientes, que retornará
verdadeiro se o registro for salvo ou falso se ocorrer algum problema.
Para funcionar dessa forma, a implementação da camada de visão deverá ser a
seguinte:

<?php require_once ABSPATH . ‘Views/includes/cabecalho.inc.php’; ?>


<form action=”<?php echo HOME_URL . ‘clientes/salvar’ ?>”
class=”formhorizontal”
method=”post”>
<input type=”hidden” name=”id” id=”cliente-id” value=”<?php echo
$cliente->id ?>”>
<div class=”form-group”>
<label for=”cliente-cpf” class=”col-sm-2 control-label”>CPF:</
label>
<div class=”col-sm-4”>
<input type=”text” class=”form-control” name=”cpf” id=”clientecpf”
maxlength=”11” value=”<?php echo $cliente->cpf ?>”>
</div>

</div>
<div class=”form-group”>
<label for=”cliente-nome” class=”col-sm-2 control-label”>Nome:</
label>
<div class=”col-sm-10”>
<input type=”text” class=”form-control” name=”nome”
id=”cliente-nome” value=”<?php echo $cliente->nome ?>”>
</div>
</div>
<div class=”form-actions”>
<button class=”btn btn-primary”><span class=”glyphicon glyphiconplus”
aria-hidden=”true”></span> Salvar</button>
<a href=”<?php echo HOME_URL . ‘clientes’ ?>” class=”btn btndefault”><
span class=”glyphicon glyphicon-repeat” aria-hidden=”true”></span>
Voltar</a>
</div>
</form>
<?php require_once ABSPATH . ‘Views/includes/rodape.inc.php’; ?>

Quanto ao método salvar() do controlador de clientes, deverá ser da seguinte forma:


// URL /clientes/salvar
public function salvar() {
// Recebe os dados via POST e converte em objeto
$cliente = (object) $_POST;
// Salvar registro no banco
$this->cliente_model->salvar( $cliente );
// Redirecionar para cliente->index
112 © Projeto de Software com Banco de Dados
UNIDADE 4 – Implemen tação de Software em MVC
header( ‘Location: ‘ . HOME_URL . ‘clientes’ );
}

Seguindo esse padrão de implementação, será possível desenvolver os demais


formulários de cadastro do nosso sistema de locadora. A seguir, faremos a
implementação dos controladores de clientes, filmes e categoria de filmes.

• Controllers/ClientesController.php: arquivo responsável por intermediar e controlar


as requisições de Clientes.
<?php
/**
* Controlador Clientes
*/
namespace Controllers;
use Classes\Controller;
use Models\ClienteModel;
class ClientesController extends Controller {
private $cliente_model;
// Método construtor da classe
public function __construct() {
// Instanciar modelos
$this->cliente_model = new ClienteModel();
parent::__construct();
}
// URL /clientes
public function index() {
// Buscar todos os registros no banco
$clientes = $this->cliente_model->filtrar_todos();
// Incluir o layout da ação
require_once ABSPATH . ‘Views/clientes/index.php’;
}
// URL /clientes/form
public function form() {
// Buscar registro quando receber o parametro ID via GET
$cliente_id = array_get( $_GET, ‘id’ );
$cliente = $this->cliente_model->filtrar_por_id( $cliente_id );
// Incluir o layout da ação
require_once ABSPATH . ‘Views/clientes/form.php’;
}
// URL /clientes/salvar
public function salvar() {
// Receber os dados via POST e converter em objeto
$cliente = (object) $_POST;
// Salvar registro no banco
$this->cliente_model->salvar( $cliente );
// Redirecionar para cliente->index
header( ‘Location: ‘ . HOME_URL . ‘clientes’ );
}
// URL /clientes/excluir
public function excluir() {
// Receber os dados via POST e converter em objeto
$cliente_id = $_GET[‘id’];
// Salvar registro no banco
$this->cliente_model->excluir( $cliente_id );
// Redirecionar para cliente->index
header( ‘Location: ‘ . HOME_URL . ‘clientes’ );
}
}

• Controllers/CategoriasController.php: arquivo responsável por intermediar e


controlar
as requisições da Categorias de Filmes.
<?php
/**
* Controlador Categorias
*/
namespace Controllers;
use Classes\Controller;
use Models\CategoriaModel;
class CategoriasController extends Controller {
private $categoria_model;
// Método construtor da classe
public function __construct() {
// Instanciar modelos
$this->categoria_model = new CategoriaModel();
parent::__construct();
}
// URL /categorias
public function index() {
// Buscar todos os registros no banco
$categorias = $this->categoria_model->filtrar_todos();
// Incluir o layout da ação
require_once ABSPATH . ‘Views/categorias/index.php’;
}
// URL /categorias/form
public function form() {
// Buscar registro quando receber o parametro ID via GET
$categoria_id = array_get( $_GET, ‘id’ );
$categoria = $this->categoria_model->filtrar_por_id( $categoria_id
);
// Incluir o layout da ação
require_once ABSPATH . ‘Views/categorias/form.php’;
}
// URL /categorias/salvar
public function salvar() {
// Receber os dados via POST e converter em objeto
$categoria = (object) $_POST;
// Salvar registro no banco
$this->categoria_model->salvar( $categoria );
// Redirecionar para categoria->index
header( ‘Location: ‘ . HOME_URL . ‘categorias’ );
}
// URL /categorias/excluir
public function excluir() {
// Receber os dados via POST e converter em objeto
$categoria_id = $_GET[‘id’];
// Salvar registro no banco
$this->categoria_model->excluir( $categoria_id );
// Redirecionar para categoria->index
header( ‘Location: ‘ . HOME_URL . ‘categorias’ );
}
}

• Controllers/FilmesController.php: arquivo responsável por intermediar e controlar


as requisições de Filmes.
<?php
/**
* Controlador Filmes
*/
namespace Controllers;
use Classes\Controller;
use Models\FilmeModel;
use Models\CategoriaModel;
class FilmesController extends Controller {
private $filme_model;
private $categoria_model;
// Método construtor da classe
public function __construct() {
// Instanciar modelos
$this->filme_model = new FilmeModel();
$this->categoria_model = new CategoriaModel();
parent::__construct();
}
// URL /filmes
public function index() {
// Buscar todos os registros no banco
$filmes = $this->filme_model->filtrar_todos();
// Incluir o layout da ação
require_once ABSPATH . ‘Views/filmes/index.php’;
}
// URL /filmes/form
public function form() {
// Buscar registro quando receber o parametro ID via GET
$filme_id = array_get( $_GET, ‘id’ );
$filme = $this->filme_model->filtrar_por_id( $filme_id );
// Buscar categorias
$categorias = $this->categoria_model->filtrar_todos();
// Incluir o layout da ação
require_once ABSPATH . ‘Views/filmes/form.php’;
}
// URL /filmes/salvar
public function salvar() {
// Receber os dados via POST e converter em objeto
$filme = (object) $_POST;
// Salvar registro no banco
$this->filme_model->salvar( $filme );
// Redirecionar para filme->index
header( ‘Location: ‘ . HOME_URL . ‘filmes’ );
}
// URL /filmes/excluir
public function excluir() {
// Receber os dados via POST e converter em objeto
$filme_id = $_GET[‘id’];
// Salvar registro no banco
$this->filme_model->excluir( $filme_id );
// Redirecionar para filme->index
header( ‘Location: ‘ . HOME_URL . ‘filmes’ );
}
}

Perceba que, no início dos controladores, foram adicionadas as classes que estão
sendo usadas pelo controlador. Por exemplo, no caso do controlador de filmes, foi
necessário importar o FilmeModel e CategoriaModel, isso porque, no formulário
Cadastro de Filmes, é necessário carregar dados do filme e as categorias disponíveis,
possibilitando, assim, a relação entre o filme e a categoria de filme (comédia, ação,
suspense, policial etc.). No caso do controlador de filmes, no início do arquivo, estão as
seguintes linhas:
<?php
/**
* Controlador Filmes
*/
namespace Controllers;
use Classes\Controller; // Usar classe dentro de Controller.php
use Models\FilmeModel; // Usar classe dentro de FilmeModel.php
use Models\CategoriaModel; // Usar classe dentro de CategoriaModel.php
...

Essa regra se aplicará a todas as classes dentro de um namespace e que dependam de


outras classes.

2.4. visão
A camada de visão é responsável por tratar toda a parte de layout do sistema. A
vantagem de utilizar o padrão MVC é que essa camada precisa conhecer as camadas
de controle e de modelo. Quanto esses últimos, não precisam conhecer a camada de
visão; dessa forma, você poderá mudar o layout do sistema sempre que precisar sem
alterar a lógica de negócio ou também criar vários temas (padrão cores e fontes)
diferentes.
No tópico anterior, foi ilustrado o modo de como as informações são enviadas do
controle para a visão, como você pôde ver, as variáveis declaradas no controlador
podem ser acessadas na visão desde que estejam dentro do mesmo método. Por
exemplo, tenho a variável $clientes = $this->cliente_model->filtrar_todos() no
controlador de clientes que, no caso, está recebendo todos os clientes cadastrados.
Veja, a seguir, como os dados dessa variável seriam descarregados dentro de uma
tabela HTML:
<table class=”table table-striped table-hover”>
<thead>
<tr>
<th>#</th>
<th>Nome</th>
<th>CPF</th>
<th>E-mail</th>
</tr>
</thead>
<tbody>
<?php while ( $cliente = $clientes->fetch_object() ) : ?>
<tr>
<td><?php echo $cliente->id ?></td>
<td><?php echo $cliente->nome ?></td>
<td><?php echo $cliente->cpf ?></td>
<td><?php echo $cliente->email ?></td>
</tr>
<?php endwhile; ?>
</tbody>
</table>
Conforme estudamos na primeira unidade, para percorrer um vetor, é necessário
utilizar uma estrutura de repetição, como: while, for, foreach ou do-while. Nesse caso,
utilizamos o while porque a variável $clientes é o resultado de uma consulta em SQL,
especificamente, um objeto da classe MySQLi_Result.
Agora que temos um exemplo de como enviar os dados do controlador para a visão,
para finalizar nosso projeto de software, implementaremos todos os arquivos da
camada de visão.

1) Views/layout/css/estilos.css: estilos em CSS do sistema.


body {
padding-top: 20px;
padding-bottom: 20px;
}
.navbar {
margin-bottom: 20px;
}
.table tbody tr td {
vertical-align: middle;
}
.form-actions {
background-color: #eee;
122 © Projeto de Software com Banco de Dados
UNIDADE 4 – Implemen tação de Software em MVC
margin-top: 30px;
padding: 20px;
text-align: center;
}
.form-actions .btn {
margin-left: 5px;
margin-right: 5px;
}

2) Views/includes/cabecalho.inc.php: cabeçalho do layout do sistema.


<!DOCTYPE html>
<html lang=”pt-BR”>
<head>
<meta charset=”UTF-8”>
<meta http-equiv=”X-UA-Compatible” content=”IE=edge”>
<meta name=”viewport” content=”width=device-width, initialscale=
1”>
<title>Sistema de Cadastro de Filmes</title>
<link rel=”stylesheet” type=”text/css” href=”https://maxcdn.
bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css”>
<link rel=”stylesheet” type=”text/css” href=”<?php echo HOME_URL;
?>Views/layout/css/estilos.css”>
</head>
<body>
<div class=”container”>
<nav class=”navbar navbar-default”>
<div class=”container-fluid”>
<div class=”navbar-header”>
<button type=”button” class=”navbar-toggle collapsed”
data-toggle=”collapse” data-target=”#navbar” aria-expanded=”false”
aria-controls=”navbar”>
<span class=”sr-only”>Toggle navigation</span>
<span class=”icon-bar”></span>
<span class=”icon-bar”></span>
<span class=”icon-bar”></span>
</button>
<a class=”navbar-brand” href=”<?php echo HOME_URL;
?>”>Locadora</a>
</div>
<div id=”navbar” class=”navbar-collapse collapse”>
<ul class=”nav navbar-nav”>
<li><a href=”<?php echo HOME_URL;
?>clientes”>Clientes</a></li>
<li><a href=”<?php echo HOME_URL;
?>filmes”>Filmes</a></li>
<li><a href=”<?php echo HOME_URL; ?>categorias”>
Categorias</a></li>
<li><a href=”<?php echo HOME_URL; ?>locacoes”>
Locações</a></li>
</ul>
</div>
</div>
</nav>

3) Views/includes/rodape.inc.php: rodapé do layout do sistema.


</div>
</body>
</html>

4) Views/clientes/index.php: arquivo responsável por listar todos os clientes.


<?php require_once ABSPATH . ‘Views/includes/cabecalho.inc.php’; ?>
<div class=”page-header”>
<h4>Cadastro de Clientes</h4>
</div>
<a href=”<?php echo HOME_URL . ‘clientes/form’ ?>” class=”btn
btnprimary”><
span class=”glyphicon glyphicon-plus” aria-hidden=”true”></span>
Novo</a>
<hr>
<table class=”table table-striped table-hover”>
<thead>
<tr>
<th>#</th>
<th>Nome</th>
<th>CPF</th>
<th>E-mail</th>
<th></th>
</tr>
</thead>
<tbody>
<?php if ( $clientes ) : ?>
<?php while ( $cliente = $clientes->fetch_object() ) : ?>
<tr>
<td><?php echo $cliente->id ?></td>
<td><?php echo $cliente->nome ?></td>
<td><?php echo $cliente->cpf ?></td>
<td><?php echo $cliente->email ?></td>
<td class=”text-right”>
<a href=”<?php echo HOME_URL . “clientes/
form?id={$cliente->id}” ?>” class=”btn btn-primary”><span
class=”glyphicon
glyphicon-pencil” aria-hidden=”true”></span></a>
<a href=”<?php echo HOME_URL . “clientes/
excluir?id={$cliente->id}” ?>” class=”btn btn-danger”><span
class=”glyphicon
glyphicon-trash” aria-hidden=”true”></span></a>
</td>
</tr>
<?php endwhile; ?>
<?php else : ?>
<tr>
<td colspan=”5”>Nenhum registro encontrado!</td>
</tr>
<?php endif; ?>
</tbody>
</table>
<?php require_once ABSPATH . ‘Views/includes/rodape.inc.php’; ?>

5) Views/clientes/form.php: layout do formulário de cadastro de clientes.


<?php require_once ABSPATH . ‘Views/includes/cabecalho.inc.php’; ?>
<form action=”<?php echo HOME_URL . ‘clientes/salvar’ ?>”
class=”formhorizontal”
method=”post”>
<input type=”hidden” name=”id” id=”cliente-id” value=”<?php echo
$cliente->id ?>”>
<div class=”form-group”>
<label for=”cliente-cpf” class=”col-sm-2 control-label”>CPF:</
label>
<div class=”col-sm-4”>
<input type=”text” class=”form-control” name=”cpf” id=”clientecpf”
maxlength=”11” value=”<?php echo $cliente->cpf ?>”>
</div>
</div>
<div class=”form-group”>
<label for=”cliente-nome” class=”col-sm-2 control-label”>Nome:</
label>
<div class=”col-sm-10”>
<input type=”text” class=”form-control” name=”nome”
id=”cliente-nome” value=”<?php echo $cliente->nome ?>”>
</div>
</div>
<div class=”form-group”>
<label for=”cliente-cep” class=”col-sm-2 control-label”>CEP:</
label>
<div class=”col-sm-4”>
<input type=”text” class=”form-control” name=”cep” id=”clientecep”
maxlength=”9” value=”<?php echo $cliente->cep ?>”>
</div>
</div>
<div class=”form-group”>
<label for=”cliente-endereco” class=”col-sm-2 controllabel”>
Endereço:</label>
<div class=”col-sm-10”>
<input type=”text” class=”form-control” name=”endereco”
id=”cliente-endereco” value=”<?php echo $cliente->endereco ?>”>
</div>
</div>
<div class=”form-group”>
<label for=”cliente-numero” class=”col-sm-2 control-label”>Número:</
label>
<div class=”col-sm-3”>
<input type=”text” class=”form-control” name=”numero”
id=”cliente-numero” maxlength=”10” value=”<?php echo $cliente->numero
?>”>
</div>
</div>
<div class=”form-group”>
<label for=”cliente-bairro” class=”col-sm-2 control-label”>Bairro:</
label>
<div class=”col-sm-10”>
<input type=”text” class=”form-control” name=”bairro” id=”-
cliente-bairro” value=”<?php echo $cliente->bairro ?>”>
</div>
</div>
<div class=”form-group”>
<label for=”cliente-cidade” class=”col-sm-2 control-label”>Cidade:</
label>
<div class=”col-sm-10”>
<input type=”text” class=”form-control” name=”cidade”
id=”cliente-cidade” value=”<?php echo $cliente->cidade ?>”>
</div>
</div>
<div class=”form-group”>
<label for=”cliente-uf” class=”col-sm-2 control-label”>UF:</
label>
<div class=”col-sm-3”>
<input type=”text” class=”form-control” name=”uf” id=”clienteuf”
maxlength=”2” value=”<?php echo $cliente->uf ?>”>
</div>
</div>
<div class=”form-group”>
<label for=”cliente-telefone” class=”col-sm-2 controllabel”>
Telefone:</label>
<div class=”col-sm-4”>
<input type=”text” class=”form-control” name=”telefone”
id=”cliente-telefone” value=”<?php echo $cliente->telefone ?>”>
</div>
</div>
<div class=”form-group”>
<label for=”cliente-email” class=”col-sm-2 control-label”>Email:</
label>
<div class=”col-sm-10”>
<input type=”text” class=”form-control” name=”email”
id=”cliente-email” value=”<?php echo $cliente->email ?>”>
</div>
</div>
<div class=”form-actions”>
<button class=”btn btn-primary”><span class=”glyphicon glyphiconplus”
aria-hidden=”true”></span> Salvar</button>
<a href=”<?php echo HOME_URL . ‘clientes’ ?>” class=”btn btndefault”><
span class=”glyphicon glyphicon-repeat” aria-hidden=”true”></span>
Voltar</a>
</div>
</form>
<?php require_once ABSPATH . ‘Views/includes/rodape.inc.php’; ?>

6) Views/categorias/index.php: arquivo responsável por listar todas as categorias de


filmes.
<?php require_once ABSPATH . ‘Views/includes/cabecalho.inc.php’; ?>
<div class=”page-header”>
<h4>Cadastro de Categorias</h4>
</div>
<a href=”<?php echo HOME_URL . ‘categorias/form’ ?>” class=”btn
btnprimary”><
span class=”glyphicon glyphicon-plus” aria-hidden=”true”></span>
Novo</a>
<hr>
<table class=”table table-striped table-hover”>
<thead>
<tr>
<th>#</th>
<th>Descrição</th>
<th></th>
</tr>
</thead>
<tbody>
<?php if ( $categorias ) : ?>
<?php while ( $categoria = $categorias->fetch_object() ) : ?>
<tr>
<td><?php echo $categoria->id ?></td>
<td><?php echo $categoria->descricao ?></td>
<td class=”text-right”>
<a href=”<?php echo HOME_URL . “categorias/
form?id={$categoria->id}” ?>” class=”btn btn-primary”><span
class=”glyphicon
glyphicon-pencil” aria-hidden=”true”></span></a>
<a href=”<?php echo HOME_URL . “categorias/
excluir?id={$categoria->id}” ?>” class=”btn btn-danger”><span
class=”glyphicon
glyphicon-trash” aria-hidden=”true”></span></a>
</td>
</tr>
<?php endwhile; ?>
<?php else : ?>
<tr>
<td colspan=”3”>Nenhum registro encontrado!</td>
</tr>
<?php endif; ?>
</tbody>
</table>
<?php require_once ABSPATH . ‘Views/includes/rodape.inc.php’; ?>

7) Views/categorias/form.php: layout do formulário de cadastro de Categorias de


Filmes.
<?php require_once ABSPATH . ‘Views/includes/cabecalho.inc.php’; ?>
<div class=”page-header”>
<h4>Cadastro de Categorias</h4>
</div>
<form action=”<?php echo HOME_URL . ‘categorias/salvar’ ?>”
class=”formhorizontal”
method=”post”>
<input type=”hidden” name=”id” id=”categoria-id” value=”<?php echo
$categoria->id ?>”>
<div class=”form-group”>
<label for=”categoria-descricao” class=”col-sm-2 controllabel”>
Descrição:</label>
<div class=”col-sm-10”>
<input type=”text” class=”form-control” name=”descricao”
id=”categoria-descricao” value=”<?php echo $categoria->descricao ?>”>
</div>
</div>
<div class=”form-actions”>
<button class=”btn btn-primary”><span class=”glyphicon glyphiconplus”
aria-hidden=”true”></span> Salvar</button>
<a href=”<?php echo HOME_URL . ‘categorias’ ?>” class=”btn
btndefault”><
span class=”glyphicon glyphicon-repeat” aria-hidden=”true”></span>
Voltar</a>
</div>
</form>
<?php require_once ABSPATH . ‘Views/includes/rodape.inc.php’; ?>

Views/filmes/index.php: arquivo responsável por listar todos os filmes.


<?php require_once ABSPATH . ‘Views/includes/cabecalho.inc.php’; ?>
<div class=”page-header”>
<h4>Cadastro de Filmes</h4>
</div>
<a href=”<?php echo HOME_URL . ‘filmes/form’ ?>” class=”btn
btnprimary”><
span class=”glyphicon glyphicon-plus” aria-hidden=”true”></span>
Novo</a>
<hr>
<table class=”table table-striped table-hover”>
<thead>
<tr>
<th>#</th>
<th>Título</th>
<th>Categoria</th>
<th></th>
</tr>
</thead>
<tbody>
<?php if ( $filmes ) : ?>
<?php while ( $filme = $filmes->fetch_object() ) : ?>
<tr>
<td><?php echo $filme->id ?></td>
<td><?php echo $filme->titulo ?></td>
<td><?php echo $filme->categoria ?></td>
<td class=”text-right”>
<a href=”<?php echo HOME_URL . “filmes/form?id={$filme-
>id}” ?>” class=”btn btn-primary”><span class=”glyphicon glyphicon-
pencil”
aria-hidden=”true”></span></a>
<a href=”<?php echo HOME_URL . “filmes/
excluir?id={$filme->id}” ?>” class=”btn btn-danger”><span
class=”glyphicon
glyphicon-trash” aria-hidden=”true”></span></a>
</td>
</tr>
<?php endwhile; ?>
<?php else : ?>
<tr>
<td colspan=”4”>Nenhum registro encontrado!</td>
</tr>
<?php endif; ?>
</tbody>
</table>
<?php require_once ABSPATH . ‘Views/includes/rodape.inc.php’; ?>

8) Views/filmes/form.php: layout do formulário de Cadastro de Filmes.


<?php require_once ABSPATH . ‘Views/includes/cabecalho.inc.php’; ?>
<div class=”page-header”>
<h4>Cadastro de Filmes</h4>
</div>
<form action=”<?php echo HOME_URL . ‘filmes/salvar’ ?>” class=”form-
horizontal”
method=”post”>
<input type=”hidden” name=”id” id=”filme-id” value=”<?php echo $filme-
>id ?>”>
<div class=”form-group”>
<label for=”filme-categoria-id” class=”col-sm-2 control©
label”>Categoria:</label>
<div class=”col-sm-10”>
<select class=”form-control” name=”categoria_id” id=”filmecategoria-
id”>
<option value=””></option>
<?php while ( $categoria = $categorias->fetch_object()
) : ?>
<option value=”<?php echo $categoria->id ?>”<?php echo
$categoria->id == $filme->categoria_id ? ‘ selected=”selected”’ : ‘’
?>><?php
echo $categoria->descricao ?></option>
<?php endwhile; ?>
</select>
</div>
</div>
<div class=”form-group”>
<label for=”filme-titulo” class=”col-sm-2 control-label”>Título:</
label>
<div class=”col-sm-10”>
<input type=”text” class=”form-control” name=”titulo”
id=”filme-titulo” value=”<?php echo $filme->titulo ?>”>
</div>
</div>
<div class=”form-actions”>
<button class=”btn btn-primary”><span class=”glyphicon glyphiconplus”
aria-hidden=”true”></span> Salvar</button>
<a href=”<?php echo HOME_URL . ‘filmes’ ?>” class=”btn btndefault”><
span class=”glyphicon glyphicon-repeat” aria-hidden=”true”></span>
Voltar</a>
</div>
</form>
<?php require_once ABSPATH . ‘Views/includes/rodape.inc.php’; ?>

Como você pôde ver, todas as páginas referentes aos cadastros de clientes, filmes e
categorias de filmes estão incluindo o cabeçalho no início e o rodapé no final da
implementação.
Fazendo isso, você pode criar o cabeçalho e o rodapé em um arquivo separado e
importá-los em todas as páginas que precisar no sistema. A vantagem é que, se
precisar mudar alguma coisa no arquivo do cabeçalho, a mudança será feita em todas
as páginas que estiverem incluindo o arquivo.
Como fazer o download do projeto
Faça o download desse projeto completo por meio do seguinte link: <https://github.
com/eduardoazevedo3/projeto-de-software-php>. Você verá que a maior parte dos
códigos estão comentados, dessa forma, você poderá compreender melhor o
funcionamento de cada recurso.
Antes de testar o projeto no seu computador, não se esqueça de criar o banco de
dados e inserir os dados de conexão no arquivo config.php localizado na raiz do
projeto.

REFERÊNCIAS BIBLIOGRÁFICAS
COSTA, Ramon Gomes; TODESCHINI, Leonardo. Web: como programar usando ferramentas livres: HTML, JavaScript,
Apache,
MySQL e PHP. Rio de Janeiro: Alta Books, 2006.
MUTO, Cláudio Adonai. PHP & MySQL: guia completo. 2. ed. Rio de Janeiro: Brasport, 2004.
OLIVIERA, Carlos A. J. Faça um site: PHP 5.2 com MySQL 5.0: comércio eletrônico: orientado por projeto. São Paulo:
Érica,
2010. 412 p.
DALL’OGLIO, Pablo. PHP Programando com orientação a Objetos. São Paulo: Novatec Editora, 2009.

Vous aimerez peut-être aussi