Skip to content

2. Uma abordagem de desenvolvimento MVC em web/PHP

Apresentamos aqui uma abordagem para o desenvolvimento de aplicações web/PHP que respeita a arquitetura MVC. Esta abordagem serve apenas para sugerir algumas possibilidades. O leitor poderá adaptá-la ao seu gosto e às suas necessidades.

  1. Começaremos por definir todas as vistas da aplicação. Estas são as páginas web apresentadas ao utilizador. Colocar-nos-emos na perspetiva do utilizador para desenhar as vistas. Distinguem-se três tipos de vistas:
    • o formulário de introdução de dados, que tem como objetivo obter informações do utilizador. Este dispõe, geralmente, de um botão para enviar ao servidor as informações introduzidas.
    • a página de resposta, que serve apenas para fornecer informações ao utilizador. Esta dispõe frequentemente de um ou mais links que permitem ao utilizador prosseguir na aplicação com outra página.
    • a página mista: o controlador enviou ao cliente uma página com informações que ele próprio gerou. Essa mesma página servirá ao cliente para fornecer ao controlador novas informações provenientes do utilizador.
  1. Cada vista dará origem a uma página PHP. Para cada uma delas:
    • definiremos o aspeto da página
    • determinar-se-ão quais são as partes dinâmicas da mesma:
      • as informações destinadas ao utilizador que deverão ser fornecidas pelo controlador como parâmetros à vista PHP. Uma solução simples é a seguinte:
        • o controlador coloca num dicionário $dReponse as informações que pretende fornecer a uma vista V
        • o controlador faz com que a vista V seja apresentada. Se esta corresponder ao ficheiro de origem V.php, esta apresentação é obtida simplesmente através da instrução include V.php.
        • A inclusão anterior é uma inclusão de código no controlador. O dicionário $dReponse, preenchido por este, é acessível diretamente através do código de V.php.
      • os dados introduzidos que deverão ser transmitidos ao programa principal para processamento. Estes deverão fazer parte de um formulário HTML (etiqueta <form>).
  1. É possível esquematizar as entradas e saídas de cada vista
  • as entradas são os dados que o controlador deverá fornecer à página PHP
  • as saídas são os dados que a página PHP deverá fornecer ao controlador da aplicação. Fazem parte de um formulário HTML e o controlador irá recuperá-las através de uma operação do tipo $_GET["param"] (método GET) ou $_POST["param"] (método POST).
  1. Frequentemente, a página final enviada ao cliente não é uma vista, mas sim uma composição de vistas. Por exemplo, a página enviada a um utilizador pode ter a seguinte forma:

A zona 1 pode ser uma barra de título, a zona 2 uma barra de menu e a zona 3 uma zona de conteúdo. No PHP, esta composição pode ser obtida através do 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>

É possível 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 vistas pode ser o único formato da resposta dada ao utilizador. Neste caso, cada resposta ao cliente deverá definir os três URL a carregar nas três áreas antes de apresentar a página de resposta. É possível generalizar este exemplo, imaginando que existam vários modelos possíveis para a página de resposta. A resposta ao cliente deverá, portanto:

  • definir o modelo a utilizar
  • definir os elementos a incluir nesse modelo
  • solicitar a exibição do modelo
  1. Escrever-se-á o código PHP/HTML de cada modelo de resposta. O seu código é geralmente simples. O do exemplo acima poderia ser:
<?php
    // inicializações para testes sem controlador
...
?>
<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, utilizar-se-á uma folha de estilo para poder alterar o «aspecto» da resposta sem ter de modificar o código PHP/HTML.

  1. Escrever-se-á o código PHP/HTML de cada vista elementar. Na maioria das vezes, terá a seguinte forma:
<?php
     // eventualmente algumas inicializações, nomeadamente na fase de depuração
    ...
?>

<balise>
...
         // aqui procuraremos minimizar o código PHP
</balise>

Note-se que uma vista elementar se integra num modelo. O seu código HTML é incorporado no código do modelo. Na maioria das vezes, este último já inclui as balizas <html>, <head> e <body>. Por isso, é pouco frequente encontrar estas balizas numa vista elementar.

  1. É possível realizar testes dos diferentes modelos de resposta e vistas elementares
  • Cada modelo de resposta é testado. Se um modelo se chamar modele1.php, aceder-se-á, através de um navegador, ao URL http://localhost/chemin/modele1.php. O modelo espera valores do controlador. Aqui, chamamo-lo diretamente e não através do controlador. O modelo não receberá os parâmetros esperados. Para que os testes sejam, ainda assim, possíveis, inicializaremos nós próprios, com constantes, os parâmetros esperados na página PHP do modelo.
  • Cada modelo é testado, bem como todas as vistas elementares. É também o momento de elaborar os primeiros elementos das folhas de estilo utilizadas.
  1. Em seguida, escreve-se a lógica de aplicação da aplicação:
  • O controlador, ou programa principal, gere geralmente várias ações. É necessário que, nas solicitações que lhe chegam, a ação a realizar esteja definida. Isto pode ser feito através de um parâmetro da solicitação a que chamaremos aqui «ação»:
    • se a solicitação provier 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 provier de um link, é possível configurá-lo:
 <a href="/C/main.php?action=uneAction">lien</a>

O controlador pode começar por ler o valor deste parâmetro e, em seguida, delegar o tratamento da solicitação a um módulo responsável por processar esse tipo de solicitação. Partimos aqui do pressuposto de que tudo era controlado por um único script chamado main.php. Se a aplicação tiver de processar as ações action1, action2, ..., actionx, é possível criar no controlador uma função por ação. Se houver muitas ações, pode-se acabar com um controlador «dinossauro». Também é possível criar scripts action1.php, action2.php, ...,actionx.php encarregados de processar cada uma das ações. O controlador responsável por processar a ação actionx limitar-se-á a carregar o código do script correspondente através de uma instrução do tipo 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 de processamento de uma ação actionx de forma relativamente independente. A inclusão do código do script actionx.php no código do controlador no momento da execução tem também a vantagem de aliviar o código carregado na memória. Apenas o código de processamento da ação em curso é carregado. Esta inclusão de código faz com que as variáveis do controlador possam entrar em conflito com as do script da ação. Veremos que podemos garantir que as variáveis do controlador se limitem a algumas variáveis bem definidas, que deverão então ser evitadas nos scripts.

  • Procure-se sistematicamente isolar o código de negócio ou o código de acesso aos dados persistentes em módulos distintos. O controlador é uma espécie de chefe de equipa que recebe pedidos dos seus clientes (clientes web) e os faz executar pelas pessoas mais adequadas (os módulos de negócio). Ao escrever o controlador, determinaremos a interface dos módulos de negócio a criar. Isto se esses módulos de negócio tiverem de ser criados. Se já existirem, então o controlador adaptar-se-á à interface desses módulos existentes.
  1. Escrever-se-á a estrutura básica dos módulos de negócio necessários ao controlador. Por exemplo, se este utilizar um módulo getCodes que devolve uma tabela de cadeias de caracteres, pode bastar, numa primeira fase, escrever:
function getCodes(){
    return array("code1","code2","code3");
}
  1. Pode-se então passar aos testes do controlador e dos scripts PHP associados:
  • o controlador, os scripts de ação, os modelos, as vistas e os recursos necessários à aplicação (imagens, etc.) são colocados na pasta DC associada ao contexto C da aplicação.
  • Feito isto, a aplicação é testada e os primeiros erros são corrigidos. Se main.php for o controlador e C o contexto da aplicação, será solicitado o URL http://localhost/C/main.php. No final desta fase, a arquitetura da aplicação está operacional. Esta fase de teste pode ser delicada, tendo em conta que dispomos de poucas ferramentas de depuração se não utilizarmos ambientes de desenvolvimento avançados e, geralmente, pagos. Pode-se recorrer às instruções `echo "mensagem"`, que escrevem no fluxo HTML enviado ao cliente e que, por isso, aparecem na página web apresentada pelo navegador.
  1. Por fim, escrevem-se as classes de negócio de que o controlador necessita. Trata-se, geralmente, do desenvolvimento clássico de uma classe PHP, na maioria das vezes independente de qualquer aplicação web. Esta será, em primeiro lugar, testada fora deste ambiente, por exemplo, com uma aplicação de consola. Quando uma classe de negócio estiver escrita, integra-se na arquitetura de implementação da aplicação web e testa-se a sua correta integração. Proceder-se-á assim para cada classe de negócio.