Programando em MVC com PHP


Autor/fonte: Daniel Ribeiro
E-mail/Url: http://www.phpbrasil.com/articles/article.php/id/1509
Tags: [ mvc ]



Digg del.icio.us

Muita gente me pergunta sobre a maneira que eu programo usando MVC com PHP. É claro que já existem vários frameworks que utilizam essa técnica no desenvolvimento PHP. Porém eu resolvi apresentar aqui o conceitual do que eu uso que pode ser de material de auxílio para outros programadores também.

Para se ter uma ideia, vamos partir para o modelo de programação orientada a objetos. Programar em MVC nada mais é do que programar também usando orientação a objetos.

Vamos pensar então no conceito de objeto. Um exemplo, um veículo, onde teremos a classe de veículo e seus métodos:

<?php
class Veiculo
{
    /**
     * Qualquer veículo tem os seus métodos padrões:
     */
    public function andar()
    {
        // ... código aqui
    }

    public function parar()
    {
        // ... código aqui
    }
}
?>

Agora digamos que temos vários veículos, temos carro, moto, bicicleta e cada um terá eventos diferentes um do outro. Para isso criamos novas classes extendendo a classe Veiculo no qual as novas classes irão herdar os métodos e propriedades da classe Veiculo:

<?php
class Bicicleta extends Veiculo
{
    // A bicicleta por sua vez contem propriedades
    public $rodas;

    // E tbm tem um metodo construtor
    public function __construct()
    {
        $this->rodas = 2;
    }

    // E tbm seus metodos
    public function trocarMarcha()
    {
        // ... código aqui
    }
}
?>

Desta forma quando instanciarmos o objeto Bicicleta, podemos utilizar os métodos de Veiculo, pois bicicleta é uma extensão de veiculo. Exemplo:

<?php
$meuVeiculo = new Bicicleta();
$meuVeiculo->trocarMarcha();
$meuVeiculo->andar();
$meuVeiculo->parar();
?>

Agora vamos construir outra classe (Automovel) que instancia veiculo

<?php
class Automovel extends Veiculo
{
    public function ligar()
    {
        // ... código aqui
    }

    public function desligar()
    {
        // ... código aqui
    }
}
?>

Desta forma quando instanciarmos o objeto Automovel, podemos utilizar os métodos de Veiculo, pois automóvel é uma extensão de veiculo. Exemplo:

<?php
$meuVeiculo = new Automovel();
$meuVeiculo->ligar();
$meuVeiculo->andar();
$meuVeiculo->parar();
$meuVeiculo->desligar();
?>

Percebeu que desta forma, se eu quiser mudar o comportamento de um Veiculo (independente do que ele seja) basta modificar a classe Veiculo, que todos os tipos de veiculos serão alterados (pois eles extendem a classe Veiculo). Isso facilita muito na manutenção do código.

Pois bem, onde queremos chegar com tudo isso? Veja na próxima página como implementamos isso num sistema MVC.

Uma aplicação MVC nada mais é do que classes principais de:

  • M - Model - Utilizada como o negócio da sua aplicação, tudo o que for utilizado para armazenamento de dados ou obtenção dos dados da aplicação);
  • V - View - Utilizada para exibir para o usuário tudo o que a aplicação produz;
  • C - Controller - Utilizada para realizar o controle integrando o Model e View (aqui é que controlamos o fluxo da aplicação).


Bem se sabemos que o Model Interage com o banco de dados, entao criamos uma classe model principal com os métodos principais que ele tem.

Obs.: O exemplo que estou colocando aqui é só um mero exemplo, para você ter uma idéia, é claro que uma classe model existem mais métodos, dependendo da sua aplicação.

<?php
class Model
{
    public function conectar()
    {
        // codigo pra conectar ao banco de dados
    }

    public function query()
    {
        // codigo pra executar uma query
    }

    public function desconectar()
    {
        // codigo pra desconectar do banco
    }
}
?>

Bem agora temos a classe View:

<?php
class View
{
    public function mostrarNaTela($template)
    {
        // mostra na tela usando o template escolhido,
        // aqui vem o codigo pra ele dar include em 
        // algum arquivo html modificando os valores 
        // que ja estao atribuidos a View e etc...
    }

    public function atribuirValor($var, $valor)
    {
        // codigo pra atribuir valores na view
    }
}
?>

Se você perceber, o Smarty segue um critério semelhante, não sei se você já usou Smarty, mas ele funciona mais ou menos assim:

<?php
$smarty = new Smarty();
// em nossa View o metodo atribuirValor()
$smarty->assign('var1', $var1);
$smarty->assign('var2', $var1);
// em nossa View o metodo mostrarNaTela()
$smarty->display('template.tpl');
?>

Já que temos métodos semelhantes, podemos então aplicar em nossa view todos os métodos do Smarty, para não ter que se preocupar em trabalhar com manipulação de templates. Ficaria mais ou menos assim a nossa view:

<?php
class View
{
    // declaro a propriedae Smarty aqui dentro da nossa 
    // view (veja que eh uma propriedade private, pois 
    // somente a classe View pode acessar ela
    private $smarty; 

    public function __construct()
    {
        // quando entao for chamado o contrutor da 
        // classe, ele instancia o objeto Smarty
        $this->smarty = new Smarty();
    }

    public function mostrarNaTela($template)
    {
        // chama o metodo do smarty pra exibir o 
        // template na tela
        $this->smarty->display($template); 
    }

    public function atribuirValor($var, $valor)
    {
        // chama o metodo do smarty para atribuir 
        // o valor a variavel
        $this->smarty->assign($var, $valor);
    }
}
?>

Talvez você esteja se perguntando "Então se eu vou usar o Smarty, porque então eu tenho que criar uma View? E usar os métodos do Smarty dentro da view? Não poderia usar diretamente o Smarty?"

Poderia, mas digamos que você posteriormente não queira mais utilizar o Smarty, e sim outro gerenciador de templates. Você teria nesse caso que mexer em sua aplicação inteira, não é? Fazendo uma classe dessa forma, você só mexe na classe View, e programa a classe View pra usar outro gerenciador de templates.

Passamos para a classe Controller, que contém os métodos básicos que farão a sua aplicação funcionar. Até mesmo métodos genéricos que você utiliza dentro da sua aplicação.

<?php
class Controller
{
    public function redirect($url)
    {
        header('Location: ' . $url);
    }

    public function error($error)
    {
        // se algum erro acontecer, chamo esse metodo,
        // que vai fazer alguma coisa (mandar um email,
        // gravar log, etc )
        $this->log($error);
    }

    public function log($mensagem)
    {
        // grava uma menagem de log em algum arquivo 
        // qualquer definido aqui
    }
}
?>

Resumindo, a classe Controller irá utilizar métodos que são genéricos para todos os módulos de sua aplicação. Agora que já temos o Model, View e Controller, vamos criar os módulos de nossa aplicação usando MVC.

Veremos agora como criar os módulos de nossa aplicação extendendo as classes MVC que acabamos de criar.

Um dos módulos é o módulo de login, então teremos o loginModel, loginView, loginController e cada um desses serão classes que extenderão suas respectivas "classes mães". Exemplo:

<?php
class loginModel extends Model
{
    /**
     * Um metodo para verficiar a senha do usuario
     *
     * @param string $usuario
     * @param string $senha
     * @return bool
     */
    public function verificarSenhaUsuario($usuario, $senha)
    {
        $this->conectar();
        $sql = "SELECT * FROM usuarios WHERE usuario = $usuario AND senha = $senha";
        $resultado = $this->query($sql);
        $this->desconectar();
        return $resultado;
    }
}
?>

A classe de View do login, além de ter os métodos herdados do View principal, também tem seus próprios métodos:

<?php
class loginView extends View
{
    /**
     * Exibe a tela de login
     *
     */
    public function exibirTelaLogin()
    {
        $this->mostrarNaTela('login.tpl');
    }

    /**
     * Exibe a tela de erro
     *
     */
    public function exibirTelaErro()
    {
        $this->mostrarNaTela('erro.tpl');
    }

    public function exibirTelaLogado()
    {
        $this->mostrarNaTela('logado.tpl');
    }
}
?>

Agora sim iremos para a classe do controlador, que irá interagir com loginModel e loginView:

<?php
class loginController extends Controller
{
    // o loginController vai agregar loginModel e 
    // loginView entao criamos esses objetos aqui

    /**
     * @var loginModel
     */
    private $model;

    /**
     * @var loginView
     */
    private $view;

    public function __construct()
    {
        // instanciamos os objetos
        $this->model = new loginModel();
        $this->view = new loginView();
    }

    public function telaLogin()
    {
        // o metodo contrutor ja chama a view do 
        // login pra exibir a tela de login
        $this->view->exibirTelaLogin();
    }

    public function fazerLogin()
    {
        // tenta ver se o usuario colocou a senha certa
        if ($this->model->verificarSenhaUsuario($_POST['usuario'], $_POST['senha'])) {
            $this->gravaSessao();
            $this->log('usuario logou');
            $this->view->exibirTelaLogado();
        } else {
            $this->log('usuario tentou logar mas nao conseguiu');
            $this->view->exibirTelaErro();
        }
    }

    /**
     * Esse metodo é private, significando que 
     * so pode ser chamado dentro da classe
     */
    private function gravaSessao()
    {
        // grava a sessao usando session ou cookie
    }

    /**
     * Esse metodo é private, significando que
     * so podem ser chamando dentro da classe
     */
    private function apagaSessao()
    {
        // limpa a sessao ou cookie
    }
}
?>

Agora que já temos o nosso controlador loginController, temos que fazer com que ele seja instanciado e chamado pelo usuário, para isso teremos um arquivo de login onde irá fazer a instância do nosso controlador do login.

Algo como login.php, este arquivo será chamado pelo browser, onde fará a requisição da sua classe.

<?php
$objLogin = new loginController();

/*
verifica que metodo o browser esta chamando, 
se nao chamar nenhum metodo, exibo a tela de login
Desta forma se for chamado a url
http://www.seusite.com.br/login.php
ele vai chamar o metodo padrao telaLogin
*/

if (!$_REQUEST['action']) {
    $_REQUEST['action'] = 'telaLogin';
}

// agora eu executo o metodo passado via url
eval('$objLogin->' . $_REQUEST['action']);
?>

Pensando dessa maneira, você terá que fazer um arquivo para cada módulo do seu sistema, se o seu sistema tiver vários módulos, então terá vários arquivos:

login.php
usuarios.php (módulo de controle de usuários)
produtos.php (módulo de controle de produtos)
...

Se formos ver, todos os arquivos que fazem as requisições de suas classes são semelhantes, entao porque não generalizar e fazer em um arquivo? Um script que pode ser usado para chamar qualquer módulo do sistema?

<?php
// instancia o modulo
eval('$instancia = new ' . $_REQUEST['modulo'] . 'Controller();');

// define uma acao default
if (!$_REQUEST['action']) {
    // isso implica que todos os controllers 
    // terao que ter um metodo chamado acaoPadrao
    $_REQUEST['action'] = 'acaoPadrao';
}

// agora eu executo o metodo passado via url
eval('$instancia' . $_REQUEST['action']);
?>

Agora você tem um arquivo que pode chamar qualquer módulo/método do seu sistema, bastando especificar na url:

http://www.seusite.com.br/main.php?module=login
http://www.seusite.com.br/main.php?module=usuario
http://www.seusite.com.br/main.php?module=produtos

O que eu escrevi aqui é mais para fim didático de como construir aplicações usando o modelo MVC, e é claro que depois de você pegar o conceito, você vai aperfeicoar o mesmo ainda mais de um jeito que funcione melhor para o seu caso específico.




Enviado por xKuRt em 22/08/2007 às 11:34


Itens relacionados

PHP5Minutes #5 - O M do MVC
Esclarecendo e entendendo o MVC
MVC em PHP com Smarty - Parte 1
MVC em PHP com Smarty - Parte 2
PHP5Minutes #6 - O V do MVC
Arquitetura MVC
PHP5Minutes #7 - O C do MVC

Avaliação

Esta publicação ainda não foi avaliada!


Avaliar:


A avaliação de publicações é restrita a membros cadastrados e logados no nosso site.



Comentários

Este artigo ainda não foi comentado ou o(s) comentário(s) que foi(ram) enviado(s) a ele ainda não foi(ram) publicado(s).


Envio de comentário:




  

Sábado, 25 de Outubro de 2014




Leitura recomendada

Guerreiro SEO

Top 5 membros

Últimos membros online

Últimos membros cadastrados



Capa do livro
Como Solucionar e Diagnosticar Defeitos no PC Através de Software


Capa do livro
Descobrindo o Linux: Entenda o Sistema Operacional GNU / Linux


Capa do livro
Android Cookbook: Problemas E Soluções Para Desenvolvedores Android





Hostnet

IMD