Construindo um framework PHP – Modelo

Quando falamos do “M” do MVC, a camada de modelo, sempre existem várias opiniões do seu papel. Acho que essa é a parte mais filosófica de todo o padrão.

Na maioria das frameworks, a parte de modelo também é a parte que faz acesso ao banco de dados. No nosso framework também vamos fazer desta maneira, mas lembre-se, isso não é uma regra. A camada de modelo não precisa obrigatoriamente fazer acesso ou ser a forma de acesso ao banco de dados. Ela pode ser para conter as nossas regras de negócio e os dados podem ser obtidos de outras fontes. Ex: arquivos e webservices.

Dica: Cuidado para não confundir validação de dados, com validação(regra) de negócio. Isso acontece com bastante frequência.

Validação de dados = verificar se um número é inteiro.

Validação de negócio = se o número for maior que 10, dividir ele por 2.

Entendido isso vamos para o que interessa. Vamos construir nossas classes de abstração de dados.Show me the code:

biblioteca/Planeta/Banco.php

class Planeta_Banco
{
	private $conexao;
	private static $instancia;

	public static function pegarInstancia()
	{
		if (!self::$instancia) {
			self::$instancia = new Planeta_Banco();
		}

		return self::$instancia;
	}

	public function pegarConexao()
	{
		return $this->conexao;
	}

	private function __construct() 
	{
		$this->conexao = new PDO('mysql:dbname=blog;host=127.0.0.1', 
                                  'root', 
                                  '123456', 
                                  array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'"));
	}

	private function __clone() 
	{
		throw Exception('Nao pode');
	}
}

É interessante verificar a utilização do padrão de projeto Singleton. Ele garante que só haverá uma única instância do objeto banco criado. Para conseguir isso, declaramos o método construtor como privado, assim, não é possível criar um novo objeto publicamente com o operador new. Para se criar esse objeto então, fazemos uma chamada estática(que não precisa de instância) e essa chamada vai fazer o controle de criação deste objeto.

biblioteca/Planeta/Banco/Tabela.php

abstract class Planeta_Banco_Tabela
{
	protected $nome;
	protected $chave;

	public function pegarNome()
	{
		return $this->nome;
	}

    /**
     *
     * @return Planeta_Banco
     */
	public function pegarBanco()
	{
		return Planeta_Banco::pegarInstancia();
	}

	public function buscarTodos()
	{
		$sql = sprintf("SELECT * FROM %s", $this->nome);
		return $this->pegarBanco()->pegarConexao()->query($sql)->fetchAll();
	}

	public function buscar($id)
	{
		$sql = sprintf("SELECT * FROM %s WHERE %s = %d", $this->nome, $this->chave, $id);
		return $this->pegarBanco()->pegarConexao()->query($sql)->fetch();
	}

	public function excluir($id)
	{
		$sql = sprintf("DELETE FROM %s WHERE %s = %d", $this->nome, $this->chave, $id);
		return $this->pegarBanco()->pegarConexao()->exec($sql);
	}

	public function inserir($dados)
	{
		unset($dados[$this->chave]);
		$campos  = array_keys($dados);
		$sql     = "INSERT INTO %s(%s) VALUES(:%s)";
		$sql     = sprintf($sql, $this->nome, \implode(",", $campos), \implode(",:", $campos));

		$confirmacao = $this->pegarBanco()->pegarConexao()->prepare($sql);
		return $confirmacao->execute($dados);
	}

	public function atualizar($dados)
	{
		$set = "";
		$id  = $dados[$this->chave];  

		unset($dados[$this->chave]);

        $campos = array_keys($dados);

		foreach ($campos as $campo) {
			$set .= sprintf("%s = :%s, ", $campo, $campo);
		}

		$set = substr($set, 0, strlen($set)-2);
		$sql = "UPDATE %s SET %s WHERE %s = %d";
		$sql = sprintf($sql, $this->nome, $set, $this->chave, $id);

        $confirmacao = $this->pegarBanco()->pegarConexao()->prepare($sql);
		return $confirmacao->execute($dados);
	}
}

Pronto! Agora vem a parte mais simples. Criar o Modelo/Tabela.

aplicacao/modelo/Postagem.php

class Postagem extends Planeta_Banco_Tabela
{
	protected $nome  = "postagem";
	protected $chave = "id";
}

E vamos modificar o nosso controlador e nossa visao também:

aplicacao/controlador/ControladorInicial.php

class ControladorInicial extends Planeta_Mvc_Controlador
{
    public function acaoInicial() 
    {
        $postagem = new Postagem();
        $this->visao->dados = $postagem->buscarTodos();
        $this->renderizar();
    }
}

aplicacao/visao/inicial/inicial.php

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta http-equiv="keywords" content="html css php planeta programacao">
    <meta http-equiv="description" content="Arquivo de demonstração">
    <title>Planeta Framework</title>
</head>
<body>
    <h1>Inicial do blog</h1>
    <p>Página com conteúdo dinâmico</p>
    <br />
    <?php foreach($this->dados as $dados):?>
        <div class="post-item">
            <h3><?php echo $dados['nome']?></h3>
            <p><?php echo $dados['descricao']?></p>
        </div>
        <br />
    <?php endforeach;?>
</body>
</html>

Agora é só escrever o restante das operações(inserir, atualizar e excluir). Espero que tenha gostado!

Published 18 January 2012