2. Uma abordagem de desenvolvimento MVC para Web/PHP
Apresentamos aqui uma abordagem para o desenvolvimento de aplicações web/PHP que seguem a arquitetura MVC. O objetivo é apenas fornecer um ponto de partida. O leitor deverá adaptá-la às suas próprias preferências e necessidades.
- Começaremos por definir todas as vistas da aplicação. Estas são as páginas web apresentadas ao utilizador. Adotaremos a perspetiva do utilizador ao projetar as vistas. Existem três tipos de vistas:
- o formulário de entrada, que se destina a recolher informações do utilizador. Normalmente inclui um botão para enviar as informações introduzidas para o servidor.
- A página de resposta, que serve apenas para fornecer informações ao utilizador. Esta inclui frequentemente um ou mais links que permitem ao utilizador continuar a utilizar a aplicação noutra página.
- a página mista: o controlador enviou ao cliente uma página contendo informações que gerou. Esta mesma página será utilizada pelo cliente para fornecer ao controlador novas informações do utilizador.
- Cada vista irá gerar uma página PHP. Para cada uma delas:
- vamos projetar o layout da página
- determinaremos quais as partes que são dinâmicas:
- as informações destinadas ao utilizador que devem ser fornecidas pelo controlador como parâmetros à vista PHP. Uma solução simples é a seguinte:
- O controlador coloca as informações que pretende fornecer a uma vista V num dicionário $dResponse
- O controlador apresenta a vista V. Se esta corresponder ao ficheiro fonte V.php, esta apresentação é conseguida simplesmente através da instrução include V.php.
- A inclusão anterior é uma inclusão de código dentro do controlador. O dicionário $dResponse preenchido pelo controlador é diretamente acessível pelo código em V.php.
- Os dados de entrada que devem ser transmitidos ao programa principal para processamento. Estes dados devem fazer parte de um formulário HTML (tag <form>).
- as informações destinadas ao utilizador que devem ser fornecidas pelo controlador como parâmetros à vista PHP. Uma solução simples é a seguinte:
- Podemos esquematizar a E/S para cada vista
![]() |
- As entradas são os dados que o controlador deve fornecer à página PHP
- As saídas são os dados que a página PHP deve fornecer ao controlador da aplicação. Fazem parte de um formulário HTML, e o controlador irá recuperá-los utilizando uma operação como $_GET["param"] (método GET) ou $_POST["param"] (método POST).
- Frequentemente, a página final enviada ao cliente não é uma única vista, mas uma composição de vistas. Por exemplo, a página enviada a um utilizador pode ter o seguinte aspeto:
![]() |
A área 1 pode ser um banner de cabeçalho, a área 2 um banner de menu e a área 3 uma área de conteúdo. Em PHP, esta composição pode ser obtida utilizando o seguinte código HTML/PHP:
<table>
<tr>
<td><?php include zone1.php ?></td>
</tr>
<tr>
<td><?php include zone2.php ?></td>
<td><?php include zone3.php ?></td>
</tr>
</table>
Pode tornar este código dinâmico escrevendo:
<table>
<tr>
<td><?php include $dReponse['urlZone1'] ?></td>
</tr>
<tr>
<td><?php include $dReponse['urlZone2'] ?></td>
<td><?php include $dReponse['urlZone3'] ?></td>
</tr>
</table>
Esta composição de visualização pode ser o único formato da resposta enviada ao utilizador. Neste caso, cada resposta ao cliente deve definir os três URLs a carregar nas três zonas antes de apresentar a página de resposta. Podemos generalizar este exemplo imaginando que existem vários modelos possíveis para a página de resposta. A resposta ao cliente deve, portanto:
- determinar o modelo a utilizar
- determinar os elementos a incluir nela
- solicitar a exibição do modelo
- Iremos escrever o código PHP/HTML para cada modelo de resposta. O seu código é geralmente simples. O código para o exemplo acima poderia ser:
<?php
// initializations for testing without a controller
...
?>
<html>
<head>
<title><?php echo $dReponse['titre'] ?></title>
<link type="text/css" href="<?php echo $dReponse['style']['url'] ?>" rel="stylesheet" />
</head>
<body>
<table>
<tr>
<td><?php include $dReponse['urlZone1'] ?></td>
</tr>
<tr>
<td><?php include $dReponse['urlZone2'] ?></td>
<td><?php include $dReponse['urlZone3'] ?></td>
</tr>
</table>
<body>
</html>
Sempre que possível, utilizaremos uma folha de estilo para que possamos alterar a «aparência» da resposta sem ter de modificar o código PHP/HTML.
- Iremos escrever o código PHP/HTML para cada vista básica. Na maioria das vezes, assumirá a seguinte forma:
<?php
// a few initializations may be necessary, particularly in the debugging phase
...
?>
<balise>
...
// here we'll try to minimize the php code
</balise>
Note que uma vista básica está incorporada num modelo. O seu código HTML está integrado no código do modelo. Na maioria das vezes, o modelo já inclui as tags <html>, <head> e <body>. Por isso, é raro encontrar estas tags numa vista básica.
- Podemos prosseguir para testar os vários modelos de resposta e vistas básicas
- Cada modelo de resposta é testado. Se um modelo se chamar modele1.php, solicitaremos o URL http://localhost/chemin/modele1.php utilizando um navegador. O modelo espera valores do controlador. Aqui, chamamo-lo diretamente, em vez de o fazermos através do controlador. O modelo não receberá os parâmetros esperados. Para permitir o teste na mesma, inicializaremos manualmente os parâmetros esperados na página PHP do modelo utilizando constantes.
- Cada modelo é testado, assim como todas as vistas básicas. Este é também o momento de desenvolver os primeiros elementos das folhas de estilo utilizadas.
- Em seguida, escrevemos a lógica da aplicação:
- O controlador, ou programa principal, geralmente lida com várias ações. A ação a ser executada deve ser definida nos pedidos que recebe. Isto pode ser feito utilizando um parâmetro de pedido, ao qual chamaremos aqui de `action`:
- se a solicitação vier de um formulário (<form>), este parâmetro pode ser um parâmetro oculto do formulário:
<form ... action="/C/main.php" method="post" ...>
<input type="hidden" name="action" value="uneAction">
...
</form>
- (continuação)
- Se o pedido vier de um link, pode configurá-lo da seguinte forma:
O controlador pode começar por ler o valor deste parâmetro e, em seguida, delegar o processamento do pedido a um módulo responsável por tratar este tipo de pedido. Aqui, partimos do princípio de que tudo é controlado por um único script chamado main.php. Se a aplicação precisar de tratar as ações action1, action2, ..., actionx, pode criar uma função para cada ação dentro do controlador. Se houver muitas ações, isto pode levar a um controlador «dinossauro». Em alternativa, pode-se criar scripts action1.php, action2.php, ..., actionx.php responsáveis por lidar com cada ação. O controlador encarregado de lidar com a ação actionx irá simplesmente carregar o código do script correspondente utilizando uma instrução como include "actionx.php". A vantagem deste método é que se trabalha fora do código do controlador. Cada membro da equipa de desenvolvimento pode, assim, trabalhar no script que lida com uma ação actionx de forma relativamente independente. Incluir o código do script actionx.php no código do controlador em tempo de execução também tem a vantagem de reduzir a quantidade de código carregado na memória. Apenas o código para lidar com a ação atual é carregado. Esta inclusão de código significa que as variáveis do controlador podem entrar em conflito com as do script de ação. Veremos que podemos limitar as variáveis do controlador a algumas bem definidas, que devem então ser evitadas nos scripts.
- Procuraremos sistematicamente isolar a lógica de negócio ou o código para aceder a dados persistentes em módulos separados. O controlador atua como uma espécie de líder de equipa que recebe pedidos dos seus clientes (clientes web) e os faz executar pelas entidades mais adequadas (os módulos de negócio). Ao escrever o controlador, determinaremos a interface dos módulos de negócio a serem escritos. Isto aplica-se se esses módulos de negócio precisarem de ser construídos. Se já existirem, então o controlador adaptar-se-á à interface desses módulos existentes.
- Iremos escrever o esqueleto dos módulos de negócio exigidos pelo controlador. Por exemplo, se o controlador utilizar um módulo `getCodes` que devolve um array de strings, podemos inicialmente escrever simplesmente:
- Podemos então passar a testar o controlador e os scripts PHP associados:
- o controlador, os scripts de ação, os modelos, as visualizações e os recursos necessários à aplicação (imagens, etc.) são colocados na pasta DC associada ao contexto C da aplicação.
- Uma vez feito isto, a aplicação é testada e os erros iniciais são corrigidos. Se main.php for o controlador e C for o contexto da aplicação, solicitaremos a URL http://localhost/C/main.php. No final desta fase, a arquitetura da aplicação está operacional. Esta fase de testes pode ser desafiante, dado que existem poucas ferramentas de depuração disponíveis se não estiver a utilizar ambientes de desenvolvimento avançados, que geralmente são pagos. Pode utilizar instruções echo "message", que escrevem no fluxo HTML enviado ao cliente e, assim, aparecem na página web apresentada pelo navegador.
- Por fim, escrevemos as classes de negócio exigidas pelo controlador. Isto envolve normalmente o desenvolvimento padrão de uma classe PHP, que é geralmente independente de qualquer aplicação web. Será primeiro testada fora deste ambiente, utilizando uma aplicação de consola, por exemplo. Assim que uma classe de negócio for escrita, integramo-la na arquitetura de implementação da aplicação web e testamos a sua integração adequada. Procedemos desta forma para cada classe de negócio.

