MVC na linguagem PHP - III

A pedido de um leitor, decidimos escrever um artigo em que exemplificamos este maravilhoso (ou não) modelo MVC utilizando a linguagem de programação PHP.

A primeirasegunda  partes já foram publicadas e hoje é a vez da terceira onde tudo começa a tornar-se mais facilmente compreendido.

Em primeiro lugar, quero referir algumas modificações que efetuei em alguns dos ficheiros que já trabalhámos.

Adicionei a constante SITE_TITLE ao ficheiro config.php, ficando a primeira secção deste ficheiro da seguinte forma:

<?php //...
//1. Base Constants
define('ROOT', dirname(__FILE__) . '/');
define('URL', 'http://localhost/mvc/');
define('SITE_TITLE', 'Simple MVC Structure Model');
//...

Na classe View foi adicionada uma função que permitirá ao utilizador definir o título (aquele que aparece na parte superior do browser).

public function setTitle($title)
{
    $this->_pageInfo['title'] = $title . ' | ' . SITE_TITLE;
}

public_html

Hoje vamos continuar a nossa jornada começando na pasta pública, ou seja, na pasta public_html. Vamos começar com o nosso maravilhoso .htaccess.

ErrorDocument 404 /404
ErrorDocument 500 /500

<IfModule mod_rewrite.c>

    RewriteEngine On

    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-l

    RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]

</IfModule>

Como pode ver, todos os pedidos serão direcionados para o ficheiro index.php com o URL completo na forma de parâmetro GET.

Falando em index.php, e que tal lhe darmos uma espreitadela? Este vai ser o ficheiro que vai iniciar toda a sequência de acontecimentos. Ora veja:

<?php

/**
 * Main file.
 *
 * @package MVC PHP Bootstrap
 */
require '../app_core/config.php';

function autoLoad($className)
{
    require DIR_LIBS . $className . '.php';
}

spl_autoload_register('autoLoad');

$bootstrap = new Bootstrap();
$bootstrap->init();

Neste ficheiro, como pode ver, o ficheiro das configurações é chamado e, de seguida, é criado uma função de auto carregamento.

O que faz esta função? Simplesmente tenta carregar uma classe indefinida. Como pode ver, eu não importo a classe Bootstrap, mas logo de seguida uso-a.

Consigo utilizá-la porque a a função de auto load chama esta classe automaticamente. Mas atenção! Este código apenas nos permite carregar automaticamente classes contidas na pasta libs.

Se neste momento experimentar correr o código nesta pasta irá receber diversos erros porque ainda não foram criados nenhuns controladores. Nem mesmo o dos erros!

Antes de continuarmos para a criação dos controladores, devemos criar os ficheiros do cabeçalho e do rodapé que são chamados quando executamos a função render.

Estes dois ficheiros deverão estar localizados na diretoria app_core/views/*.php, onde * corresponde a header e a footer.

A minha proposta para o ficheiro do cabeçalho é a seguinte:

<!doctype html>
<html lang='en-EN'>

<head>
    <title><?php echo (isset($this->_pageInfo['title'])) ? $this->_pageInfo['title'] : SITE_TITLE; ?></title>

    <meta charset='utf-8'>
    <meta name='viewport' content='width=device-width, initial-scale=1'>

    <link rel='stylesheet' href='<?php echo URL; ?>css/template.css' type='text/css' media='all'/>
    <link rel='stylesheet' href='<?php echo URL; ?>css/normalize.css' type='text/css' media='all'/>
</head>

<body>
<div id='header'>
    <strong>MVCPHPB</strong>
    | <a href="<?php echo URL; ?>">Home</a>
    | <a href="<?php echo URL; ?>page">Page</a>
    | <a href="<?php echo URL; ?>posts">Posts</a>
</div>

<div id="wrap">

Onde já temos o título da página que será igual ao título que é definido utilizando a função que referi no início do artigo, ou apenas o nome do site.

Deixei também uma pequena introdução à estrutura HTML do site e uma pista àquilo que iremos criar: iremos criar uma página estática (Page) e uma página dinâmica com alguns itens de uma base de dados (Posts).

Estou também a utilizar o normalize.css e uma folha de estilos própria com alguns ajustes de forma a distinguir melhor cada uma das partes do site. Aqui está o template.css (deve ser colocado na pasta css):

#header,
#wrap,
#footer {
  padding: 20px;
}

#header {
  background: rgba(0,0,0,0.12);
}

#footer {
  background: rgba(0,0,0,0.5);
  color: #fff;
}

Vamos agora ver o rodapé. O rodapé está localizado no ficheiro app_core/views/footer.php e o conteúdo deve ser algo semelhante ao seguinte:

</div>

<footer id="footer">
    <strong><strong>MVCPHPB</strong></strong> Footer
</footer>

</body>
</html>

Controladores

Depois de termos “montado” a estrutura, devemos passar à criação das páginas. Em primeiro lugar, vamos criar o controlador do erro.

<?php

namespace Controller;

class Error extends Controller
{

    function __construct()
    {
        parent::__construct('error');
    }

    function index($error = '404')
    {
        $data = array();

        switch ($error) {
            case '404':
                $data['title'] = 'Error 404';
                $data['msg'] = "Not found. There is nothing here.";
                break;
            case '500':
            default:
                $data['title'] = 'Error 500';
                $data['msg'] = "Internal Server Error. Probably we did something wrong.";
                break;
        }

        $this->view->setTitle($data['title']);
        $this->view->setData($data);
        $this->view->render('error/index');
    }

}

Os controladores devem pertencer à namespace Controller e devem ter, obrigatoriamente, o seu construtor presente no formato mostrado acima.

Este é um controlador que só terá o método _index _relacionado com as páginas pois não irá ser utilizado mais nenhum. Acima pode visualizar que este método irá receber um argumento que, por padrão, é ‘404’.

De seguida, algumas informações são atribuídas dependendo do erro em questão. Depois o título da página é definido e, mais tarde, os dados são enviados para a view.

Falando em view, esta é renderizada logo de seguida. A _view _que colocámos é error/index, então o ficheiro PHP deverá encontrar-se em app_core/views/error/index.php.

Se experimentar correr o código neste momento, deverá receber um erro por não encontrar a _View _da página de erro.

Vamos então visualizar a view que corresponde à página de erro:

<h1> <?php echo $this->_data['title'] ?></h1>

<p><?php echo $this->_data['msg']; ?></p>

É simples. Serve apenas para mostrar que ocorreu um erro. Mas não podemos continuar assim pois ao abrirmos a página inicial estamos apenas a ver um erro.

Vamos então criar o controlador da página inicial, que deve conter o seguinte código:

<?php

namespace Controller;

class Index extends Controller
{

    function __construct()
    {
        parent::__construct('index');
    }

    function index()
    {
        $this->view->setTitle('Home');
        $this->view->render('index/index');
    }

}

E o ficheiro da sua _view _deverá ter qualquer coisa que deseje. Eu, por exemplo, coloquei:

<h1>MVC PHP Bootstrap (MVCPHPB)</h1>

<p>This is the main page of this website that is a simple mvc structure model example.</p>

<p>Esta é a página principal deste site que é um exemplo de modelo de estrutura MVC simples.</p>

Coloque o que queira. De momento, se aceder à página inicial deverá visualizar a página inicial propriamente dita e se tentar, eventualmente, abrir qualquer outra possível página, irá ver a página de erro 404.

No próximo tutorial iremos ver a criação de uma página dinâmica com um modelo. Pode, entretanto, experimentar criar mais páginas ou até mesmo criar mais métodos para sub-páginas.