Mas afinal, o que é o MVC?

Model–view–controller (MVC) is a software architecture pattern that separates the representation of information from the user’s interaction with it.

Wikipedia

MVC é um padrão de arquitetura de software que separa a informação (e as suas regras de negócio) da interface com a qual o usuário interage.

É uma forma de estruturar seu projeto/aplicação de forma que a interface de interação (view) esteja separada do controle da informação em si (models), separação essa que é intermediada por uma outra camada controladora (controllers).

Não vou entrar em detalhes profundos sobre a arquitetura de um sistema baseado no MVC nem vou – por enquanto! – mostrar como criar um MVC do zero, mas vou tentar explicar cada uma das três camadas e dar exemplos de código do CakePHP, que é um framework de PHP que – ao meu ver – faz um bom uso do MVC.

Model (ou modelo)

O model é a camada que representa os seus dados, provendo meios de acesso (leitura e escrita) à esses dados.

A regra é simples: tudo que diz respeito à escrita, validação e leitura dos dados está dentro da camada model, não necessariamente dentro do model em si, mas dentro da camada model.

Vemos aqui um exemplo de model de produtos (que vai prover o acesso à tabela products, no banco de dados) no arquivo Product.php:

<?php

/**
 * Model de produtos
 */
class Product extends AppModel {

/**
 * Regras de validação
 * 
 * @var array
 */
 public $validate = array(
 'name' => array(
 'notEmpty' => array('rule' => 'notEmpty')
 ),
 'description' => array(
 'notEmpty' => array('rule' => 'notEmpty'),
 'minLength' => array('rule' => array('minLength', 100))
 ),
 'price' => array(
 'decimal' => array('rule' => array('decimal', 2))
 )
 );

/**
 * Lista dos produtos mais recentes
 *
 * @param int $limit Quantidade de produtos
 * @param array $params Parâmetros extras de busca
 * 
 * @return array
 */
 public function recent($limit = 5, $params = array()) {
 $params = Hash::merge(array(
 'conditions' => array('Product.published' => true),
 'order' => array('Product.created' => 'DESC'),
 'limit' => $limit
 ), $params);

 return $this->find('all', $params);
 }

}

Aqui temos um model bem simples, onde definimos as regras de validação e um método que vai auxiliar a encontrar os produtos mais recentes.

Não vou entrar nos detalhes do CakePHP, além do mais acho que o código é bem auto-explicativo.

Somente através desse model será possível cadastrar e buscar produtos, e quando um usuário for cadastrar ou editar uma notícia, aquelas regras de validação devem ser respeitadas, ou seja:

  • O título não pode ser vazio
  • A descrição não pode ser vazia nem ter menos de 100 caracteres
  • O preço precisa ser no formato decimal, com 2 casas decimais

Para saber mais sobre models no CakePHP, consulte a documentação: http://book.cakephp.org/2.0/en/models.html

Agora podemos partir para a camada que vai fazer uso desse model, pedindo uma lista de produtos..

Controller (ou controlador)

No controller você tem métodos públicos que são chamados de actions, cada action é responsável por uma “página” do seu site/sistema. É o controller quem decide:

  1. Qual model usar;
  2. Quais pedidos fazer pro model;
  3. Qual combinação de views será usada para exibir os dados retornados pelo model.

Atente que não é o controller que busca os dados (responsabilidade do model) e nem é ele quem exibe os dados (responsabilidade da view)… ele está ali justamente pra controlar os dois e a aplicação como um todo.

Vamos à um exemplo de controller no arquivo ProductsController.php:

<?php

/**
 * Controller de produtos
 */
class ProductsController extends AppController {

/**
 * Página inicial, mostra os produtos mais recentes
 * 
 * @return void
 */
 public function index() {
 $products = $this->Product->recent();

 $this->set(compact('products'));
 }

/**
 * Visualização de um único produto
 * 
 * @param int $id ID do produto
 * 
 * @return void
 */
 public function view($id) {
 $this->Product->id = $id;
 if (!$this->Product->exists()) {
 throw new NotFoundException('Produto não encontrado');
 }

 $product = $this->Product->read();

 $this->set(compact('product'));
 }

}

Aqui temos duas actons:

  • Uma action (index) vai pedir (para o model) a lista de produtos mais recentes;
  • Outra action (view) vai pedir (para o model) os dados de um único produto.

Para saber mais sobre controllers no CakePHP, consulte a documentação: http://book.cakephp.org/2.0/en/controllers.html

Agora podemos exibir esses dados na camada responsável por isso…

View (ou visualização)

É na view que o seu sistema interage com o usuário. Tudo que ele ver (HTML / XML / RSS / CSV) deve ser gerado e exibido através dessa camada. A view, por sua vez, tem como responsabilidade:

  • Manipular os dados para – e apenas para – exibição;
  • Exibir os dados

Mas a view não faz nenhum tipo de escrita/persistência no seu sistema… ela não salva dados no banco, na sessão e etc.. E ela também não busca esses dados, pois eles devem – obrigatoriamente – serem entregues pela camada controller.

Vamos ver então um exemplo de listagem dos produtos, no arquivo index.ctp:

<h1>Produtos mais recentes</h1>
<?php foreach ($products as $product): ?>
<article id="product-<?php echo $product['Product']['id'] ?>">
<h2><?php echo $product['Product']['name'] ?></h2>
<p><?php echo $product['Product']['description'] ?></p>
<p>Por apenas <?php echo $this->Number->currency($product['Product']['price'], 'BRL') ?>!</p>
</article>
<?php endforeach ?>

Aqui temos uma mistura de HTML e PHP, e também fazemos uso do NumberHelper, um Helper do CakePHP para ajudar na formatação de números.

Se você quiser saber mais sobre views no CakePHP, consulte a documentação: http://book.cakephp.org/2.0/en/views.html

Conclusão

Com o MVC você conseguirá organizar seu projeto de forma que tudo tenha seu lugar, e cada camada com sua responsabilidade, permitindo um trabalho muitos mais “centrado” e modularizado.

Fonte: Thiago Belem