4. Uma aplicação ilustrativa
Propomos ilustrar o método anterior com um exemplo de cálculo de impostos.
4.1. O problema
Pretendemos escrever um programa que permita calcular o imposto de um contribuinte. Consideramos o caso simplificado de um contribuinte que tenha apenas o seu salário para declarar:
- calcula-se o número de quotas do trabalhador nbParts = nbEnfants/2 + 1 se não for casado, nbEnfants/2 + 2 se for casado, em que nbEnfants é o número de filhos. O número de quotas é aumentado em 0,5 se houver três ou mais filhos.
- calcula-se o seu rendimento tributável R = 0,72 * S, em que S é o seu salário anual
- calcula-se o seu coeficiente familiar Q = R/N
- calcula-se o seu imposto I com base nos seguintes dados
| Cada linha tem 3 campos de limite: coeffR, coeffN. Para calcular o imposto I, procura-se a primeira linha em que QF ≤ limite. Por exemplo, se QF = 30000, encontrar-se-á a linha: 31810 0,2 3309,5. O imposto I é, então, igual a 0,2*R - 3309,5*nbParts. Se QF for tal que a relação QF <= limite nunca for verificada, então são utilizados os coeficientes da última linha: 0 0,65 49062, o que dá o imposto I = 0,65*R - 49062*nbParts. |
4.2. A base de dados
Os dados anteriores são registados numa base de dados MySQL denominada dbimpots. O utilizador seldbimpots, com a palavra-passe mdpseldbimpots, tem acesso de leitura ao conteúdo da base de dados. Esta possui uma única tabela denominada impots, cuja estrutura é a seguinte:

O seu conteúdo é o seguinte:

4.3. A arquitetura MVC da aplicação
A aplicação terá a seguinte arquitetura MVC:
![]() |
- O controlador main.php será o controlador genérico apresentado anteriormente
- o pedido do cliente é enviado ao controlador sob a forma de uma solicitação com o formato main.php?action=xx. O valor do parâmetro «action» determina o script do bloco ACTIONS a ser executado. O script de ação executado devolve ao controlador uma variável que indica o estado em que a aplicação web deve ser colocada. Com base nesse estado, o controlador ativará um dos geradores de vistas para enviar a resposta ao cliente.
- impots-data.php é a classe responsável por fornecer ao controlador os dados de que este necessita
- impots-calcul.php é a classe de negócio que permite o cálculo do imposto
4.4. A classe de acesso aos dados
A classe de acesso aos dados foi concebida para ocultar à aplicação web a origem dos dados. Na sua interface, encontra-se um método getData que fornece os três tabuleiros de dados necessários ao cálculo do imposto. No nosso exemplo, os dados são obtidos de uma base de dados MySQL. Para tornar a classe independente do tipo real do SGBD, utilizaremos a biblioteca pear::DB descrita no anexo. O código da classe é o seguinte:
<?php
// bibliotecas
require_once 'DB.php';
class impots_data{
// classe de acesso à fonte de dados DBIMPOTS
// atributos
var $sDSN; // a cadeia de ligação
var $sDatabase; // o nome da base de dados
var $oDB; // ligação à base de dados
var $aErreurs; // lista de erros
var $oRésultats; // resultado de uma consulta
var $connecté; // valor booleano que indica se está ou não ligado à base de dados
var $sQuery; // a última consulta executada
// construtor
function impots_data($dDSN){
// $dDSN: dicionário que define a ligação a estabelecer
// $dDSN['sgbd']: o tipo de SGBD ao qual é necessário ligar-se
// $dDSN['host']: o nome do servidor que o aloja
// $dDSN['database']: o nome da base de dados à qual é necessário ligar-se
// $dDSN['user']: um utilizador da base de dados
// $dDSN['mdp']: a sua palavra-passe
// cria em $oDB uma ligação à base de dados definida por $dDSN sob a identidade de $dDSN['user']
// se a ligação for bem-sucedida
// insere em $sDSN a cadeia de ligação à base de dados
// insere em $sDataBase o nome da base de dados à qual se está a ligar
// define $connecté como verdadeiro
// se a ligação falhar
// insere as mensagens de erro adequadas na lista $aErreurs
// encerra a ligação, se necessário
// define $connecté como falso
// limpa a lista de erros
$this->aErreurs=array();
// é criada uma ligação à base de dados $sDSN
$this->sDSN=$dDSN["sgbd"]."://".$dDSN["user"].":".$dDSN["mdp"]."@".$dDSN["host"]."/".$dDSN["database"];
$this->sDatabase=$dDSN["database"];
$this->connect();
// ligado?
if( ! $this->connecté) return;
// a ligação foi bem-sucedida
$this->connecté=TRUE;
}//criador
// ------------------------------------------------------------------
function connect(){
// (re)ligação à base de dados
// limpar lista de erros
$this->aErreurs=array();
// a criar uma ligação à base de dados $sDSN
$this->oDB=DB::connect($this->sDSN,true);
// erro?
if(DB::iserror($this->oDB)){
// registo do erro
$this->aErreurs[]="Echec de la connexion à la base [".$this->sDatabase."] : [".$this->oDB->getMessage()."]";
// a ligação falhou
$this->connecté=FALSE;
// fim
return;
}
// estamos ligados
$this->connecté=TRUE;
}//ligar
// ------------------------------------------------------------------
function disconnect(){
// se estivermos ligados, encerramos a ligação à base $sDSN
if($this->connecté){
$this->oDB->disconnect();
// estamos desconectados
$this->connecté=FALSE;
}//se
}//desligar
// -------------------------------------------------------------------
function execute($sQuery){
// $sQuery: consulta a executar
// a consulta é guardada
$this->sQuery=$sQuery;
// está-se ligado?
if(! $this->connecté){
// regista-se o erro
$this->aErreurs[]="Pas de connexion existante à la base [$this->sDatabase]";
// fim
return;
}//if
// execução da consulta
$this->oRésultats=$this->oDB->query($sQuery);
// erro?
if(DB::iserror($this->oRésultats)){
// regista-se o erro
$this->aErreurs[]="Echec de la requête [$sQuery] : [".$this->oRésultats->getMessage()."]";
// retorno
return;
}//if
}//executar
// ------------------------------------------------------------------
function getData(){
// recuperam-se as 3 séries de dados: limites, coeffr, coeffn
$this->execute('select limites, coeffR, coeffN from impots');
// erros?
if(count($this->aErreurs)!=0) return array();
// percorre-se o resultado da consulta
while ($ligne = $this->oRésultats->fetchRow(DB_FETCHMODE_ASSOC)) {
$limites[]=$ligne['limites'];
$coeffr[]=$ligne['coeffR'];
$coeffn[]=$ligne['coeffN'];
}//enquanto
return array($limites,$coeffr,$coeffn);
}//getDataImpots
}//classe
?>
Um programa de teste poderia ser o seguinte:
<?php
// biblioteca
require_once "c-impots-data.php";
require_once "DB.php";
// teste da classe impots-data
ini_set('track_errors','on');
ini_set('display_errors','on');
// configuração básica do dbimpots
$dDSN=array(
"sgbd"=>"mysql",
"user"=>"seldbimpots",
"mdp"=>"mdpseldbimpots",
"host"=>"localhost",
"database"=>"dbimpots"
);
// início de sessão
$oImpots=new impots_data($dDSN);
// erros?
if(checkErreurs($oImpots)){
exit(0);
}
// acompanhamento
echo "Connecté à la base...\n";
// recuperação dos dados de limites, coeffr, coeffn
list($limites,$coeffr,$coeffn)=$oImpots->getData();
// erros?
if( ! checkErreurs($oImpots)){
// conteúdo
echo "données : \n";
for($i=0;$i<count($limites);$i++){
echo "[$limites[$i],$coeffr[$i],$coeffn[$i]]\n";
}//for
}//if
// desligar-se
$oImpots->disconnect();
// acompanhamento
echo "Déconnecté de la base...\n";
// fim
exit(0);
// ----------------------------------
function checkErreurs(&$oImpots){
// erros?
if(count($oImpots->aErreurs)!=0){
// visualização
for($i=0;$i<count($oImpots->aErreurs);$i++){
echo $oImpots->aErreurs[$i]."\n";
}//para
// erros
return true;
}//if
// sem erros
return false;
}//checkErreurs
?>
A execução deste programa de teste produz os seguintes resultados:
Connecté à la base...
données :
[12620,0,0]
[13190,0.05,631]
[15640,0.1,1290.5]
[24740,0.15,2072.5]
[31810,0.2,3309.5]
[39970,0.25,4900]
[48360,0.3,6898]
[55790,0.35,9316.5]
[92970,0.4,12106]
[127860,0.45,16754]
[151250,0.5,23147.5]
[172040,0.55,30710]
[195000,0.6,39312]
[0,0.65,49062]
Déconnecté de la base...
4.5. A classe de cálculo do imposto
Esta classe permite calcular o imposto de um contribuinte. São fornecidos ao seu construtor os dados necessários para esse cálculo. Em seguida, este encarrega-se de calcular o imposto correspondente. O código da classe é o seguinte:
<?php
class impots_calcul{
// classe de cálculo do imposto
// construtor
function impots_calcul(&$perso,&$data){
// $perso: dicionário com as seguintes chaves
// filhos(a): número de filhos
// salário: salário anual
// casado(a): valor booleano que indica se o contribuinte é casado ou não
// imposto(s): imposto a pagar calculado por este construtor
// $data: dicionário com as seguintes chaves
// limites: tabela dos limites das faixas de rendimento
// coeficientes: tabela dos coeficientes do rendimento
// coeffn: tabela dos coeficientes do número de quotas
// as 3 tabelas têm o mesmo número de elementos
// cálculo do número de quotas
if($perso['marié'])
$nbParts=$perso['enfants']/2+2;
else $nbParts=$perso['enfants']/2+1;
if ($perso['enfants']>=3) $nbParts+=0.5;
// rendimento tributável
$revenu=0.72*$perso['salaire'];
// quociente familiar
$QF=$revenu/$nbParts;
// procura da faixa de imposto correspondente a QF
$nbTranches=count($data['limites']);
$i=0;
while($i<$nbTranches-2 && $QF>$data['limites'][$i]) $i++;
// o imposto
$perso['impot']=floor($data['coeffr'][$i]*$revenu-$data['coeffn'][$i]*$nbParts);
}//construtor
}//classe
?>
Um programa de teste poderia ser o seguinte:
<?php
// biblioteca
require_once "c-impots-data.php";
require_once "c-impots-calcul.php";
// configuração de base do dbimpots
$dDSN=array(
"sgbd"=>"mysql",
"user"=>"seldbimpots",
"mdp"=>"mdpseldbimpots",
"host"=>"localhost",
"database"=>"dbimpots"
);
// início de sessão
$oImpots=new impots_data($dDSN);
// erros?
if(checkErreurs($oImpots)){
exit(0);
}
// acompanhamento
echo "Connecté à la base...\n";
// recuperação de dados de limites, coeffr, coeffn
list($limites,$coeffr,$coeffn)=$oImpots->getData();
// erros?
if(checkErreurs($oImpots)){
exit(0);
}
// desligar sessão
$oImpots->disconnect();
// acompanhamento
echo "Déconnecté de la base...\n";
// cálculo de um imposto
$dData=array('limites'=>&$limites,'coeffr'=>&$coeffr,'coeffn'=>&$coeffn);
$dPerso=array('enfants'=>2,'salaire'=>200000,'marié'=>true,'impot'=>0);
new impots_calcul($dPerso,$dData);
dump($dPerso);
$dPerso=array('enfants'=>3,'salaire'=>200000,'marié'=>false,'impot'=>0);
new impots_calcul($dPerso,$dData);
dump($dPerso);
$dPerso=array('enfants'=>3,'salaire'=>20000,'marié'=>true,'impot'=>0);
new impots_calcul($dPerso,$dData);
dump($dPerso);
$dPerso=array('enfants'=>3,'salaire'=>2000000,'marié'=>true,'impot'=>0);
new impots_calcul($dPerso,$dData);
dump($dPerso);
// fim
exit(0);
// ----------------------------------
function checkErreurs(&$oImpots){
// erros?
if(count($oImpots->aErreurs)!=0){
// visualização
for($i=0;$i<count($oImpots->aErreurs);$i++){
echo $oImpots->aErreurs[$i]."\n";
}//para
// erros
return true;
}//if
// sem erros
return false;
}//checkErreurs
?>
A execução deste programa de testes produz os seguintes resultados:
Connecté à la base...
Déconnecté de la base...
[enfants,2] [salaire,200000] [marié,1] [impot,22506]
[enfants,3] [salaire,200000] [marié,] [impot,22506]
[enfants,3] [salaire,20000] [marié,1] [impot,0]
[enfants,3] [salaire,2000000] [marié,1] [impot,706752]
4.6. Funcionamento da aplicação
Quando a aplicação web de cálculo de impostos é iniciada, é apresentada a seguinte vista [v-formulaire]:
![]() |
O utilizador preenche os campos e solicita o cálculo do imposto:
![]() |
Note-se que o formulário é regenerado no estado em que o utilizador o validou e que, além disso, apresenta o montante do imposto a pagar. O utilizador pode cometer erros de introdução de dados. Estes são-lhe assinalados por uma página de erros a que chamaremos vista [v-erreurs].
![]() |
![]() |
A ligação [Retour au formulaire de saisie] permite ao utilizador recuperar o formulário tal como o validou.
![]() |
Por fim, o botão [Effacer le formulaire] repõe o formulário no seu estado inicial, c.a.d, tal como o utilizador o recebeu na solicitação inicial.
4.7. Análise da arquitetura MVC da aplicação
A aplicação tem a seguinte arquitetura MVC:
![]() |
Acabámos de descrever as duas classes impots-data.php e impots-calcul.php. Passamos agora a descrever os restantes elementos da arquitetura.
4.8. O controlador da aplicação
O controlador main.php da aplicação é aquele que foi descrito na primeira parte deste capítulo. Trata-se de um controlador genérico independente da aplicação.
<?php
// controlador genérico
// leitura da configuração
include 'config.php';
// inclusão de bibliotecas
for($i=0;$i<count($dConfig['includes']);$i++){
include($dConfig['includes'][$i]);
}//para
// inicia ou retoma a sessão
session_start();
$dSession=$_SESSION["session"];
if($dSession) $dSession=unserialize($dSession);
// recupera-se a ação a realizar
$sAction=$_GET['action'] ? strtolower($_GET['action']) : 'init';
$sAction=strtolower($_SERVER['REQUEST_METHOD']).":$sAction";
// a sequência de ações está normal?
if( ! enchainementOK($dConfig,$dSession,$sAction)){
// sequência anormal
$sAction='enchainementinvalide';
}//if
// processamento da ação
$scriptAction=$dConfig['actions'][$sAction] ?
$dConfig['actions'][$sAction]['url'] :
$dConfig['actions']['actionInvalide']['url'];
include $scriptAction;
// envio da resposta (visualização) ao cliente
$sEtat=$dSession['etat']['principal'];
$scriptVue=$dConfig['etats'][$sEtat]['vue'];
include $scriptVue;
// fim do script — não se deve chegar aqui, a menos que haja um bug
trace ("Erreur de configuration.");
trace("Action=[$sAction]");
trace("scriptAction=[$scriptAction]");
trace("Etat=[$sEtat]");
trace("scriptVue=[$scriptVue]");
trace ("Vérifiez que les script existent et que le script [$scriptVue] se termine par l'appel à finSession.");
exit(0);
// ---------------------------------------------------------------
function finSession(&$dConfig,&$dReponse,&$dSession){
// $dConfig: dicionário de configuração
// $dSession: dicionário contendo as informações da sessão
// $dReponse: o dicionário de argumentos da página de resposta
// registo da sessão
if(isset($dSession)){
//: os parâmetros da solicitação são colocados na sessão
$dSession['requete']=strtolower($_SERVER['REQUEST_METHOD'])=='get' ? $_GET :
strtolower($_SERVER['REQUEST_METHOD'])=='post' ? $_POST : array();
$_SESSION['session']=serialize($dSession);
session_write_close();
}else{
// sem sessão
session_destroy();
}
// apresenta-se a resposta
include $dConfig['vuesReponse'][$dReponse['vuereponse']]['url'];
// fim do script
exit(0);
}//fim da sessão
//--------------------------------------------------------------------
function enchainementOK(&$dConfig,&$dSession,$sAction){
// verifica se a ação atual está autorizada em relação ao estado anterior
$etat=$dSession['etat']['principal'];
if(! isset($etat)) $etat='sansetat';
// verificação da ação
$actionsautorisees=$dConfig['etats'][$etat]['actionsautorisees'];
$autorise= ! isset($actionsautorisees) || in_array($sAction,$actionsautorisees);
return $autorise;
}
//--------------------------------------------------------------------
function dump($dInfos){
// exibe um dicionário de informações
while(list($clé,$valeur)=each($dInfos)){
echo "[$clé,$valeur]<br>\n";
}//while
}//acompanhamento
//--------------------------------------------------------------------
function trace($msg){
echo $msg."<br>\n";
}//acompanhamento
?>
4.9. As ações da aplicação web
Existem quatro ações:
- get:init: é a ação que é acionada durante o pedido inicial sem parâmetros ao controlador. Gera a vista «formulário» vazia.
- post:effacerformulaire: ação acionada pelo botão [Effacer le formulaire]. Gera a vista [v-formulaire] vazia.
- post:calculerimpot: ação acionada pelo botão [Calculer l'impôt]. Gera ou a vista [v-formulaire] com o montante do imposto a pagar, ou a vista [v-erreurs].
- get:retourformulaire: ação acionada pelo link [Retour au formulaire de saisie]. Gera a vista [v-formulaire] pré-preenchida com os dados errados.
Estas ações estão configuradas da seguinte forma no ficheiro de configuração:
<?php
…
// configuração das ações da aplicação
$dConfig['actions']['get:init']=array('url'=>'a-init.php');
$dConfig['actions']['post:calculerimpot']=array('url'=>'a-calculimpot.php');
$dConfig['actions']['get:retourformulaire']=array('url'=>'a-retourformulaire.php');
$dConfig['actions']['post:effacerformulaire']=array('url'=>'a-init.php');
$dConfig['actions']['enchainementinvalide']=array('url'=>'a-enchainementinvalide.php');
$dConfig['actions']['actionInvalide']=array('url'=>'a-actioninvalide.php');
A cada ação está associado o script responsável pelo seu processamento. Cada ação levará a aplicação web a um estado definido pelo elemento $dSession['etat']['principal']. Este estado destina-se a ser guardado na sessão. Além disso, a ação regista no dicionário $dReponse as informações úteis para a exibição da vista associada ao novo estado em que a aplicação se irá encontrar.
4.10. Os estados da aplicação web
Existem dois:
- [e-formulaire]: estado em que são apresentadas as diferentes variantes da vista [v-formulaire].
- [e-erreurs]: estado em que é apresentada a vista [v-erreurs].
As ações autorizadas nestes estados são as seguintes:
<?php
…
// configuração dos estados da aplicação
$dConfig['etats']['formulaire']=array(
'actionsautorisees'=>array('post:calculerimpot','get:init','post:effacerformulaire'),
'vue'=>'e-formulaire.php');
$dConfig['etats']['erreurs']=array(
'actionsautorisees'=>array('get:retourformulaire','get:init'),
'vue'=>'e-erreurs.php');
$dConfig['etats']['sansetat']=array('actionsautorisees'=>array('get:init'));
Num estado, as ações autorizadas correspondem aos destinos URL dos links ou botões [submit] da vista associada ao estado. Além disso, a ação «get:init» está sempre autorizada. Isto permite ao utilizador recuperar o URL main.php da lista de URL do seu navegador e reproduzi-lo novamente, independentemente do estado da aplicação. Trata-se de uma espécie de reinicialização «manual». O estado «sem estado» existe apenas no arranque da aplicação.
A cada estado da aplicação está associado um script responsável por gerar a vista associada a esse estado:
- estado [e-formulaire]: script e-formulaire.php
- relatório [e-erreurs]: script e-erreurs.php
O relatório [e-formulaire] apresentará a vista [v-formulaire] com variantes. Com efeito, a vista [v-formulaire] pode ser apresentada em branco, pré-preenchida ou com o montante do imposto. A ação que levará a aplicação ao estado [e-formulaire] especifica, na variável $dSession['etat']['principal'], o estado principal da aplicação. O controlador utiliza apenas esta informação. Na nossa aplicação, a ação que conduz ao estado [e-formulaire] irá adicionar a $dSession['etat']['secondaire'] uma informação complementar que permite ao gerador da resposta saber sedeve gerar um formulário vazio, pré-preenchido, com ou sem o montante do imposto. Poderíamos ter procedido de forma diferente, considerando que existiam aqui três estados diferentes e, portanto, três geradores de visualização a escrever.
4.11. O ficheiro de configuração da aplicação web config.php
<?php
// configuração do PHP
ini_set("register_globals","off");
ini_set("display_errors","off");
ini_set("expose_php","off");
// lista de módulos a incluir
$dConfig['includes']=array('c-impots-data.php','c-impots-calcul.php');
// controlador da aplicação
$dConfig['webapp']=array('titre'=>"Calculez votre impôt");
// configuração das vistas da aplicação
$dConfig['vuesReponse']['modele1']=array('url'=>'m-reponse.php');
$dConfig['vuesReponse']['modele2']=array('url'=>'m-reponse2.php');
$dConfig['vues']['formulaire']=array('url'=>'v-formulaire.php');
$dConfig['vues']['erreurs']=array('url'=>'v-erreurs.php');
$dConfig['vues']['formulaire2']=array('url'=>'v-formulaire2.php');
$dConfig['vues']['erreurs2']=array('url'=>'v-erreurs2.php');
$dConfig['vues']['bandeau']=array('url'=>'v-bandeau.php');
$dConfig['vues']['menu']=array('url'=>'v-menu.php');
$dConfig['style']['url']='style1.css';
// configuração das ações da aplicação
$dConfig['actions']['get:init']=array('url'=>'a-init.php');
$dConfig['actions']['post:calculerimpot']=array('url'=>'a-calculimpot.php');
$dConfig['actions']['get:retourformulaire']=array('url'=>'a-retourformulaire.php');
$dConfig['actions']['post:effacerformulaire']=array('url'=>'a-init.php');
$dConfig['actions']['enchainementinvalide']=array('url'=>'a-enchainementinvalide.php');
$dConfig['actions']['actionInvalide']=array('url'=>'a-actioninvalide.php');
// configuração dos relatórios da aplicação
$dConfig['etats']['e-formulaire']=array(
'actionsautorisees'=>array('post:calculerimpot','get:init','post:effacerformulaire'),
'vue'=>'e-formulaire.php');
$dConfig['etats']['e-erreurs']=array(
'actionsautorisees'=>array('get:retourformulaire','get:init'),
'vue'=>'e-erreurs.php');
$dConfig['etats']['sansetat']=array('actionsautorisees'=>array('get:init'));
// configuração do modelo da aplicação
$dConfig["DSN"]=array(
"sgbd"=>"mysql",
"user"=>"seldbimpots",
"mdp"=>"mdpseldbimpots",
"host"=>"localhost",
"database"=>"dbimpots"
);
?>
4.12. As ações da aplicação web
4.12.1. Funcionamento geral dos scripts de ação
- Um script de ação é chamado pelo controlador de acordo com o parâmetro «action» que este recebeu do cliente.
- Após a execução, o script de ação deve indicar ao controlador o estado em que a aplicação deve ser colocada. Este estado deve ser indicado em $dSession['etat']['principal'].
- Um script de ação pode querer inserir informações na sessão. Para tal, insere-as no dicionário $dSession, sendo que este dicionário é automaticamente guardado na sessão pelo controlador no final do ciclo pedido-resposta.
- Um script de ação pode ter informações a passar para as vistas. Este aspeto é independente do controlador. Trata-se da interface entre as ações e as vistas, uma interface específica de cada aplicação. No exemplo aqui analisado, as ações fornecerão informações aos geradores de vistas através de um dicionário denominado $dReponse.
4.12.2. A ação get:init
É a ação que gera o formulário vazio. O ficheiro de configuração mostra que será processada pelo script a-init.php:
O código do script a-init.php é o seguinte:
<?php
// é apresentado o formulário de introdução de dados
$dSession['etat']=array('principal'=>'e-formulaire', 'secondaire'=>'init');
?>
Este script limita-se a definir, em $dSession['etat']['principal'], o estado em que a aplicação deve encontrar-se, o estado [e-formulaire], e fornece em $dSession['etat']['secondaire'] uma especificação sobre esse estado. O ficheiro de configuração mostra-nos que o controlador executará o script e-formulaire.php para gerar a resposta ao cliente.
<?php
…
$dConfig['etats']['e-formulaire']=array(
'actionsautorisees'=>array('post:calculerimpot','get:init','post:effacerformulaire'),
'vue'=>'e-formulaire.php');
O script e-formulaire.php irá gerar a vista [v-formulaire] nas suas variantes [init] e c.a.d. O formulário está vazio.
4.12.3. A ação post:calculerimpot
Esta é a ação que permite calcular o imposto com base nos dados introduzidos no formulário. O ficheiro de configuração indica que é o script a-calculimpot.php que irá processar esta ação:
O código do script a-calculimpot.php é o seguinte:
<?php
// pedido de cálculo de impostos
// verifica-se primeiro a validade dos parâmetros
$sOptMarie=$_POST['optmarie'];
if($sOptMarie!='oui' && $sOptMarie!='non'){
$erreurs[]="L'état marital [$sOptMarie] est erroné";
}
$sEnfants=trim($_POST['txtenfants']);
if(! preg_match('/^\d{1,3}$/',$sEnfants)){
$erreurs[]="Le nombre d'enfants [$sEnfants] est erroné";
}
$sSalaire=trim($_POST['txtsalaire']);
if(! preg_match('/^\d+$/',$sSalaire)){
$erreurs[]="Le salaire annuel [$sSalaire] est erroné";
}
// se houver erros, o processo termina
if(count($erreurs)!=0){
// preparação da página de erros
$dReponse['erreurs']=&$erreurs;
$dSession['etat']=array('principal'=>'e-erreurs','secondaire'=>'saisie');
return;
}//if
// os dados introduzidos estiverem corretos
// recuperam-se os dados necessários para o cálculo do imposto
if(! $dSession['limites']){
// os dados não se encontram na sessão
// recuperam-se da fonte de dados
list($erreurs,$limites,$coeffr,$coeffn)=getData($dConfig['DSN']);
// se houver erros, é apresentada a página de erros
if(count($erreurs)!=0){
// preparação da página de erros
$dReponse['erreurs']=&$erreurs;
$dSession['etat']=array('principal'=>'e-erreurs','secondaire'=>'database');
return;
}//if
// sem erros — os dados são colocados na sessão
$dSession['limites']=&$limites;
$dSession['coeffr']=&$coeffr;
$dSession['coeffn']=&$coeffn;
}//se
// aqui temos os dados necessários para o cálculo do imposto
// calcula-se o imposto
$dData=array('limites'=>&$dSession['limites'],
'coeffr'=>&$dSession['coeffr'],
'coeffn'=>&$dSession['coeffn']);
$dPerso=array('enfants'=>$sEnfants,'salaire'=>$sSalaire,'marié'=>($sOptMarie=='oui'),'impot'=>0);
new impots_calcul($dPerso,$dData);
// preparação da página de resposta
$dSession['etat']=array('principal'=>'e-formulaire','secondaire'=>'calculimpot');
$dReponse['impot']=$dPerso['impot'];
return;
//-----------------------------------------------------------------------
function getData($dDSN){
// ligação à fonte de dados definida pelo dicionário $dDSN
$oImpots=new impots_data($dDSN);
if(count($oImpots->aErreurs)!=0) return array($oImpots->aErreurs);
// recuperação dos dados de limites, coeffr, coeffn
list($limites,$coeffr,$coeffn)=$oImpots->getData();
// desligar-se
$oImpots->disconnect();
// retornar o resultado
if(count($oImpots->aErreurs)!=0) return array($oImpots->aErreurs);
else return array(array(),$limites,$coeffr,$coeffn);
}//getData
O script faz o que tem de fazer: calcular o imposto. Deixamos ao leitor a tarefa de descodificar o código do processamento. O nosso interesse centra-se nos estados que podem ocorrer na sequência desta ação:
- os dados introduzidos estão incorretos ou o acesso aos dados falha: a aplicação é colocada no estado [e-erreurs]. O ficheiro de configuração mostra que é o script e-erreurs.php que ficará encarregue de gerar a vista de resposta:
<?php
…
$dConfig['etats']['e-erreurs']=array(
'actionsautorisees'=>array('get:retourformulaire','get:init'),
'vue'=>'e-erreurs.php');
- em todos os outros casos, a aplicação é colocada no estado [e-formulaire] com a variante de cálculo de impostos indicada em $dSession['etat']['secondaire']. O ficheiro de configuração indica que é o script e-formulaire.php que irá gerar a vista de resposta. Este irá utilizar o valor de $dSession['etat']['secondaire'] para gerar um formulário pré-preenchido com os valores introduzidos pelo utilizador e, além disso, o montante do imposto.
4.12.4. A ação post:effacerformulaire
Está associada, por configuração, ao script a-init.php já descrito.
4.12.5. A ação get:retourformulaire
Permite regressar ao estado [e-formulaire] a partir do estado [e-erreurs]. É o script a-retourformulaire.php que processa esta ação:
O script a-retourformulaire.php é o seguinte:
<?php
// exibe-se o formulário de introdução de dados
$dSession['etat']=array('principal'=>'e-formulaire','secondaire'=>'retourformulaire');
?>
Basta solicitar que a aplicação seja colocada no estado [e-formulaire] na sua variante [retourformulaire]. O ficheiro de configuração indica-nos que o controlador executará o script e-formulaire.php para gerar a resposta ao cliente.
<?php
…
$dConfig['etats']['e-formulaire']=array(
'actionsautorisees'=>array('post:calculerimpot','get:init','post:effacerformulaire'),
'vue'=>'e-formulaire.php');
O script e-formulaire.php irá gerar a vista [v-formulaire] nas suas variantes [retourformulaire] e c.a.d. o formulário pré-preenchido com os valores introduzidos pelo utilizador, mas sem o montante do imposto.
4.13. A sequência de ações inválida
As ações válidas a partir de um determinado estado da aplicação são definidas por configuração:
<?php
…
// configuração dos estados da aplicação
$dConfig['etats']['e-formulaire']=array(
'actionsautorisees'=>array('post:calculerimpot','get:init','post:effacerformulaire'),
'vue'=>'e-formulaire.php');
$dConfig['etats']['e-erreurs']=array(
'actionsautorisees'=>array('get:retourformulaire','get:init'),
'vue'=>'e-erreurs.php');
$dConfig['etats']['sansetat']=array('actionsautorisees'=>array('get:init'));
Já explicámos esta configuração. Se for detetada uma sequência inválida de ações, o script a-enchainementinvalide.php é executado:
O código deste script é o seguinte:
<?php
// sequência de ações inválida
$dReponse['erreurs']=array("Enchaînement d'actions invalide");
$dSession['etat']=array('principal'=>'e-erreurs','secondaire'=>'enchainementinvalide');
?>
Consiste em colocar a aplicação no estado [e-erreurs]. Em $dSession['etat']['secondaire'], fornecemos uma informação que será utilizada pelo gerador da página de erros. Como já vimos, esse gerador é o e-erreurs.php:
<?php
…
$dConfig['etats']['e-erreurs']=array(
'actionsautorisees'=>array('get:retourformulaire','get:init'),
'vue'=>'e-erreurs.php');
Veremos o código deste gerador mais tarde. A visualização enviada ao cliente é a seguinte:

4.14. As vistas da aplicação
4.14.1. Exibição da vista final
Vamos ver como o controlador envia a resposta ao cliente, uma vez executada a ação solicitada por este:
<?php
…
....
// inicia-se ou retoma-se a sessão
session_start();
$dSession=$_SESSION["session"];
if($dSession) $dSession=unserialize($dSession);
// recupera-se a ação a realizar
$sAction=$_GET['action'] ? strtolower($_GET['action']) : 'init';
$sAction=strtolower($_SERVER['REQUEST_METHOD']).":$sAction";
// A sequência de ações está normal?
if( ! enchainementOK($dConfig,$dSession,$sAction)){
// sequência anormal
$sAction='enchainementinvalide';
}//if
// processamento da ação
$scriptAction=$dConfig['actions'][$sAction] ?
$dConfig['actions'][$sAction]['url'] :
$dConfig['actions']['actionInvalide']['url'];
include $scriptAction;
// envio da resposta (visualização) ao cliente
$sEtat=$dSession['etat']['principal'];
$scriptVue=$dConfig['etats'][$sEtat]['vue'];
include $scriptVue;
.....
// ---------------------------------------------------------------
function finSession(&$dConfig,&$dReponse,&$dSession){
// $dConfig: dicionário de configuração
// $dSession: dicionário contendo as informações da sessão
// $dReponse: o dicionário de argumentos da página de resposta
// registo da sessão
...
// envio da resposta ao cliente
include $dConfig['vuesReponse'][$dReponse['vuereponse']]['url'];
// fim do script
exit(0);
}//fim da sessão
Após o retorno de um script de ação, o controlador recupera em $dSession['etat']['principal'] o estado em que deve colocar a aplicação. Este estado foi definido pela ação que acabou de ser executada. O controlador faz então com que seja executado o gerador de visualização associado ao estado. Encontra o nome deste no ficheiro de configuração. A função do gerador de visualização é a seguinte:
- define em $dReponse['vuereponse'] o nome do modelo de resposta a utilizar. Esta informação será passada ao controlador. Um modelo é uma composição de vistas elementares que, quando reunidas, formam a vista final.
- prepara as informações dinâmicas a apresentar na vista final. Este ponto é independente do controlador. Trata-se da interface entre o gerador de vistas e a vista final. É específica de cada aplicação.
- termina obrigatoriamente com a chamada à função finSession do controlador. Esta função irá
- guardar a sessão
- enviar a resposta
O código da função finSession é o seguinte:
<?php
…
// ---------------------------------------------------------------
function finSession(&$dConfig,&$dReponse,&$dSession){
// $dConfig: dicionário de configuração
// $dSession: dicionário contendo as informações da sessão
// $dReponse: o dicionário de argumentos da página de resposta
// registo da sessão
...
//: envio da resposta ao cliente
include $dConfig['vuesReponse'][$dReponse['vuereponse']]['url'];
// fim do script
exit(0);
}//fim da sessão
A visualização enviada ao utilizador é definida pela entidade $dReponse['vuereponse'], que define o modelo a utilizar para a resposta final.
4.14.2. Modelo da resposta
A aplicação irá gerar as suas diferentes respostas de acordo com o seguinte modelo único:
![]() |
Este modelo está associado à chave «modéle1» do dicionário $dConfig['vuesreponse']:
O script m-reponse.php é responsável por gerar este modelo:
<html>
<head>
<title>Application impots</title>
<link type="text/css" href="<?php echo $dReponse['urlstyle'] ?>" rel="stylesheet" />
</head>
<body>
<?php
include $dReponse['vue1'];
?>
<hr>
<?php
include $dReponse['vue2'];
?>
</body>
</html>
Este script tem três elementos dinâmicos colocados num dicionário $dReponse e associados às seguintes chaves:
- urlstyle: URL da folha de estilo do modelo
- vue1: nome do script responsável por gerar a vista vue1
- vue2: nome do script responsável por gerar a vista vue2
Um gerador de vista que pretenda utilizar o modelo «modelo1» deverá definir estes três elementos dinâmicos. Definimos agora as vistas elementares que podem substituir os elementos [vue1] e [vue2] do modelo.
4.14.3. A vista elementar v-bandeau.php
O script v-bandeau.php gera uma vista que será colocada na zona [vue1]:
<table>
<tr>
<td><img src="univ01.gif"></td>
<td>
<table>
<tr>
<td><div class='titre'><?php echo $dReponse['titre'] ?></div></td>
</tr>
<tr>
<td><div class='resultat'><?php echo $dReponse['resultat']?></div></td>
</tr>
</table>
</td>
</tr>
</table>
O gerador de visualização deverá definir dois elementos dinâmicos colocados num dicionário $dReponse e associados às seguintes chaves:
- título: título a apresentar
- resultado: montante do imposto a pagar
4.14.4. A vista elementar v-formulaire.php
A parte [vue2] corresponde à vista [v-formulaire] ou à vista [v-erreurs]. A vista [v-formulaire] é gerada pelo script v-formulaire.php:
<form method="post" action="main.php?action=calculerimpot">
<table>
<tr>
<td class="libelle">Etes-vous marié(e)</td>
<td class="valeur">
<input type="radio" name="optmarie" <?php echo $dReponse['optoui'] ?> value="oui">oui
<input type="radio" name="optmarie" <?php echo $dReponse['optnon'] ?> value="non">non
<td>
<tr>
<td class="libelle">Nombre d'enfants</td>
<td class="valeur">
<input type="text" class="text" name="txtenfants" size="3" value="<?php echo $dReponse['enfants'] ?>"
</td>
</tr>
<tr>
<td class="libelle">Salaire annuel</td>
<td class="valeur">
<input type="text" class="text" name="txtsalaire" size="10" value="<?php echo $dReponse['salaire'] ?>"
</td>
</tr>
</table>
<hr>
<input type="submit" class="submit" value="Calculer l'impôt">
</form>
<form method="post" action="main.php?action=effacerformulaire">
<input type="submit" class="submit" value="Effacer le formulaire">
</form>
As partes dinâmicas desta vista, que deverão ser definidas pelo gerador de vistas, estão associadas às seguintes chaves do dicionário $dReponse:
- optoui: estado do botão de opção com o nome optoui
- optnon: estado do botão de opção com o nome optnon
- enfants: número de filhos a inserir no campo txtenfants
- salário: salário anual a inserir no campo txtsalário
4.14.5. A vista elementar v-erreurs.php
A vista [v-erreurs] é gerada pelo script v-erreurs.php:
Les erreurs suivantes se sont produites :
<ul>
<?php
for($i=0;$i<count($dReponse["erreurs"]);$i++){
echo "<li class='erreur'>".$dReponse["erreurs"][$i]."</li>\n";
}//for
?>
</ul>
<div class="info"><?php echo $dReponse["info"] ?></div>
<br>
<a href="<?php echo $dReponse["href"] ?>"><?php echo $dReponse["lien"] ?></a>
As partes dinâmicas desta vista, a definir pelo gerador de vistas, estão associadas às seguintes chaves do dicionário $dReponse:
- erros: tabela de mensagens de erro
- info: mensagem informativa
- ligação: texto de uma ligação
- href: URL de destino do link acima
4.14.6. A folha de estilo
Todas as vistas são «formatas» por uma folha de estilo. Para alterar o aspeto visual da aplicação, deve-se modificar a sua folha de estilo. A seguinte folha de estilo style1.css:
div.menu {
background-color: #FFD700;
color: #F08080;
font-weight: bolder;
text-align: center;
}
td.separateur {
background: #FFDAB9;
width: 20px;
}
table.modele2 {
width: 600px;
}
BODY {
background-image : url(standard.jpg);
margin-left : 0px;
margin-top : 6px;
color : #4A1919;
font-size: 10pt;
font-family: Arial, Helvetica, sans-serif;
scrollbar-face-color:#F2BE7A;
scrollbar-arrow-color:#4A1919;
scrollbar-track-color:#FFF1CC;
scrollbar-3dlight-color:#CBB673;
scrollbar-darkshadow-color:#CBB673;
}
div.titre {
font: 30pt Garamond;
color: #FF8C00;
background-color: Yellow;
}
table.menu {
background-color: #ADD8E6;
}
A:HOVER {
text-decoration: underline;
color: #FF0000;
background-color : transparent;
}
A:ACTIVE {
text-decoration: underline;
color : #BF4141;
background-color : transparent;
}
A:VISITED {
color : #BF4141;
background-color : transparent;
}
.error {
color : red;
font-weight : bold;
}
INPUT.text {
margin-left : 3px;
font-size:8pt;
font-weight:bold;
color:#4A1919;
background-color:#FFF6E0;
border-right:1px solid;
border-left:1px solid;
border-top:1px solid;
border-bottom:1px solid;
}
td.libelle {
background-color: #F0FFFF;
color: #0000CD;
}
td.valeur {
background-color: #DDA0DD;
}
DIV.resultat {
background-color : #FFA07A;
font : bold 12pt;
}
div.info {
color: #FA8072;
}
li.erreur {
color: #DC143C;
}
INPUT.submit {
margin-left : 6px;
font-size:8pt;
font-weight:bold;
color:#4A1919;
background-color:#FFF1CC;
border-right:1px solid;
border-left:1px solid;
border-top:1px solid;
border-bottom:1px solid;
}
4.15. Os geradores de vistas
4.15.1. Função de um gerador de vistas
Recorde-se a sequência de código do controlador que executa um gerador de visualização:
<?php
…
// processamento da ação
$scriptAction=$dConfig['actions'][$sAction] ?
$dConfig['actions'][$sAction]['url'] :
$dConfig['actions']['actionInvalide']['url'];
include $scriptAction;
// envio da resposta (visualização) ao cliente
$sEtat=$dSession['etat']['principal'];
$scriptVue=$dConfig['etats'][$sEtat]['vue'];
include $scriptVue;
Um gerador de vista está associado ao estado no qual a aplicação será colocada. A ligação entre o estado e o gerador de vista é definida por configuração:
<?php
…
// configuração dos estados da aplicação
$dConfig['etats']['e-formulaire']=array(
'actionsautorisees'=>array('post:calculerimpot','get:init','post:effacerformulaire'),
'vue'=>'e-formulaire.php');
$dConfig['etats']['e-erreurs']=array(
'actionsautorisees'=>array('get:retourformulaire','get:init'),
'vue'=>'e-erreurs.php');
$dConfig['etats']['sansetat']=array('actionsautorisees'=>array('get:init'));
Já indicámos qual era a função de um gerador de visualização. Vamos relembrá-la aqui. Um gerador de visualização:
- define em $dReponse['vuereponse'] o nome do modelo de resposta a utilizar. Esta informação será passada ao controlador. Um modelo é uma composição de vistas elementares que, quando reunidas, formam a vista final.
- prepara as informações dinâmicas a apresentar na vista final. Este aspeto é independente do controlador. Trata-se da interface entre o gerador de vistas e a vista final. É específica de cada aplicação.
- termina obrigatoriamente com a chamada à função finSession do controlador. Esta função irá
- guardar a sessão
- enviar a resposta
4.15.2. O gerador de visualização associado ao estado [e-formulaire]
O script responsável por gerar a vista associada ao estado [e-formulaire] chama-se e-formulaire.php:
<?php
…
$dConfig['etats']['e-formulaire']=array(
'actionsautorisees'=>array('post:calculerimpot','get:init','post:effacerformulaire'),
'vue'=>'e-formulaire.php');
O seu código é o seguinte:
<?php
// prepara-se a resposta do formulário
$dReponse['titre']=$dConfig['webapp']['titre'];
$dReponse['vuereponse']='modele1';
$dReponse['vue1']=$dConfig['vues']['bandeau']['url'];
$dReponse['vue2']=$dConfig['vues']['formulaire']['url'];
$dReponse['urlstyle']=$dConfig['style']['url'];
$dReponse['titre']=$dConfig['webapp']['titre'];
// configuração de acordo com o tipo de formulário a gerar
$type=$dSession['etat']['secondaire'];
if($type=='init'){
// formulário em branco
$dReponse['optnon']='checked';
}//if
if($type=='calculimpot'){
// é necessário voltar a apresentar os parâmetros de introdução de dados armazenados na consulta
$dReponse['optoui']=$_POST['optmarie']=='oui' ? 'checked' : '';
$dReponse['optnon']=$dReponse['optoui'] ? '' : 'checked';
$dReponse['enfants']=$_POST['txtenfants'];
$dReponse['salaire']=$_POST['txtsalaire'];
$dReponse['resultat']='Impôt à payer : '.$dReponse['impot'].' F';
}//if
if($type=='retourformulaire'){
// é necessário voltar a apresentar os parâmetros de introdução de dados armazenados na sessão
$dReponse['optoui']=$dSession['requete']['optmarie']=='oui' ? 'checked' : '';
$dReponse['optnon']=$dReponse['optoui']=='' ? 'checked' : '';
$dReponse['enfants']=$dSession['requete']['txtenfants'];
$dReponse['salaire']=$dSession['requete']['txtsalaire'];
}//if
// envia-se a resposta
finSession($dConfig,$dReponse,$dSession);
?>
Note-se que o gerador de visualizações cumpre as condições impostas a um gerador de visualizações:
- definir em $dReponse['vuereponse'] o modelo de resposta a utilizar
- passar informações para esse modelo. Neste caso, estas são passadas através do dicionário $dReponse.
- terminar com a chamada à função finSession do controlador
Aqui, o modelo utilizado é «modelo1». Assim, o gerador define as duas informações de que este modelo necessita: $dReponse['vue1'] e $dReponse['vue2'].
No caso específico da nossa aplicação, a vista associada ao estado [e-formulaire] depende de uma informação armazenada na variável $dSession['etat']['secondaire']. Trata-se de uma escolha de desenvolvimento. Outra aplicação poderia optar por transmitir informações complementares de outra forma. Além disso, neste caso, todas as informações necessárias para a exibição da vista final são colocadas no dicionário $dReponse. Mais uma vez, trata-se de uma escolha que cabe ao programador. O estado [e-formulaire] pode ocorrer após quatro ações diferentes: init, calcularimposto, regressar ao formulário, apagar o formulário. A vista a apresentar não é exatamente a mesma em todos os casos. Por isso, distinguiram-se aqui três casos em $dSession['etat']['secondaire']:
- init: o formulário é apresentado vazio
- calculo do imposto: o formulário é apresentado com o montante do imposto e os dados que conduziram ao seu cálculo
- retourformulaire: o formulário é apresentado com os dados inicialmente introduzidos
Acima, o script e-formulaire.php utiliza esta informação para apresentar a resposta de acordo com estas três variantes.
4.15.3. A vista associada ao relatório [e-erreurs]
O script responsável por gerar a vista associada ao relatório [e-erreurs] chama-se e-erreurs.php e é o seguinte:
<?php
// preparamos a resposta de erros
$dReponse['titre']=$dConfig['webapp']['titre'];
$dReponse['vuereponse']='modele1';
$dReponse['vue1']=$dConfig['vues']['bandeau']['url'];
$dReponse['vue2']=$dConfig['vues']['erreurs']['url'];
$dReponse['urlstyle']=$dConfig['style']['url'];
$dReponse['titre']=$dConfig['webapp']['titre'];
$dReponse['lien']='Retour au formulaire de saisie';
$dReponse['href']='main.php?action=retourformulaire';
// informações adicionais
$type=$dSession['etat']['secondaire'];
if($type=='database'){
$dReponse['info']="Veuillez avertir l'administrateur de l'application";
}
// envia-se a resposta
finSession($dConfig,$dReponse,$dSession);
?>
4.15.4. Exibição da vista final
Os dois scripts que geram as duas vistas finais terminam ambos com a chamada à função finSession do controlador:
<?php
…
function finSession(&$dConfig,&$dReponse,&$dSession){
// $dConfig: dicionário de configuração
// $dSession: dicionário contendo as informações da sessão
// $dReponse: o dicionário de argumentos da página de resposta
....
// apresenta a resposta
include $dConfig['vuesReponse'][$dReponse['vuereponse']]['url'];
// fim do script
exit(0);
}//fim da sessão
A visualização enviada ao utilizador é definida pela entidade $dReponse['vuereponse'], que define o modelo a utilizar para a resposta final. Para os relatórios [e-formulaire] e [e-erreurs], este modelo foi definido como «modelo1»:
Este modelo corresponde, por configuração, ao script m-reponse.php:
4.16. Alterar o modelo de resposta
Partimos do princípio de que se decide alterar o aspeto visual da resposta enviada ao cliente e pretendemos compreender as repercussões que isso acarreta ao nível do código.
4.16.1. O novo modelo
A estrutura da resposta será agora a seguinte:
![]() |
Este modelo será denominado «modele2» e o script responsável por gerar este modelo será denominado «m-reponse2.php»:
O script correspondente a este modelo é o seguinte:
<html>
<head>
<title>Application impots</title>
<link type="text/css" href="<?php echo $dReponse['urlstyle'] ?>" rel="stylesheet" />
</head>
<body>
<table class='modele2'>
<!-- início do banner -->
<tr>
<td colspan="2"><?php include $dReponse['vue1']; ?></td>
</tr>
<!-- fim do banner -->
<tr>
<!-- início do menu -->
<td><?php include $dReponse['vue2']; ?></td>
<!-- fim do menu -->
<!-- início da zona 3 -->
<td><?php include $dReponse['vue3']; ?></td>
<!-- fim da zona 3 -->
</tr>
</table>
</body>
</html>
Os elementos dinâmicos do modelo são os seguintes:
- $dReponse['urlstyle']: a folha de estilo a utilizar
- $dReponse['vue1']: o script a utilizar para gerar [vue1]
- $dReponse['vue2']: o script a utilizar para gerar [vue2]
- $dReponse['vue3']: o script a utilizar para gerar [vue3]
Estes elementos deverão ser definidos pelos criadores das visualizações.
4.16.2. As diferentes páginas de resposta
A aplicação apresentará agora as seguintes respostas ao utilizador. Na chamada inicial, a página de resposta será a seguinte:
![]() |
Se o utilizador fornecer dados válidos, o imposto é calculado:
![]() |
Se cometer erros na introdução de dados, é apresentada a página de erros:
![]() |
Se utilizar o link [Retour au formulaire de saisie], volta a aceder ao formulário tal como o validou:
![]() |
Se, no exemplo acima, utilizar o link [Réinitialiser le formulaire], irá encontrar um formulário em branco:
![]() |
Note-se que a aplicação utiliza, de facto, as mesmas ações que anteriormente. Apenas o aspeto das respostas mudou.
4.16.3. As vistas elementares
A vista elementar [vue1] será, tal como no exemplo anterior, associada ao script v-bandeau.php:
<table>
<tr>
<td><img src="univ01.gif"></td>
<td>
<table>
<tr>
<td><div class='titre'><?php echo $dReponse['titre'] ?></div></td>
</tr>
<tr>
<td><div class='resultat'><?php echo $dReponse['resultat']?></div></td>
</tr>
</table>
</td>
</tr>
</table>
Esta vista tem dois elementos dinâmicos:
- $dReponse['titre']: título a apresentar
- $dReponse['resultat']: montante do imposto a pagar
A vista elementar [vue2] será associada ao seguinte script v-menu.php:
<table class="menu">
<tr>
<td><div class="menu">Options</div></td>
</tr>
<?php
for($i=0;$i<count($dReponse['liens']);$i++){
echo '<tr><td><div class="option"><a href="'.
$dReponse['liens'][$i]['url'].
'">'.$dRespostaQZXW2HTMLBWydsaWVucyddZQXQZXW2HTMLBWyRpXQZQXQZXW2HTMLBWyd0ZXh0ZSddZQX."</a></div></td></tr>\n";
}//$i
?>
</table>
Esta vista contém os seguintes elementos dinâmicos:
- $dReponse['liens']: tabela de links a apresentar em [vue2]. Cada elemento da tabela é um dicionário com duas chaves:
- 'url': URL de destino do link
- 'texto': texto do link
A vista elementar [vue3] será associada ao script v-formulaire2.php se se pretender apresentar o formulário de introdução de dados, ou ao script v-erreurs2.php se se pretender apresentar a página de erros. O código do script v-formulaire2.php é o seguinte:
<form method="post" action="main.php?action=calculerimpot">
<table>
<tr>
<td class="libelle">Etes-vous marié(e)</td>
<td class="valeur">
<input type="radio" name="optmarie" <?php echo $dReponse['optoui'] ?> value="oui">oui
<input type="radio" name="optmarie" <?php echo $dReponse['optnon'] ?> value="non">non
</td>
</tr>
<tr>
<td class="libelle">Nombre d'enfants</td>
<td class="valeur">
<input type="text" class="text" name="txtenfants" size="3" value="<?php echo $dReponse['enfants'] ?>"
</td>
</tr>
<tr>
<td class="libelle">Salaire annuel</td>
<td class="valeur">
<input type="text" class="text" name="txtsalaire" size="10" value="<?php echo $dReponse['salaire'] ?>"
</td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" class="submit" value="Calculer l'impôt"></td>
</tr>
</table>
</form>
As partes dinâmicas desta vista, que deverão ser definidas pelo gerador de vistas, estão associadas às seguintes chaves do dicionário $dReponse:
- optoui: estado do botão de opção com o nome optoui
- optnon: estado do botão de opção com o nome optnon
- enfants: número de filhos a inserir no campo txtenfants
- salário: salário anual a inserir no campo txtsalário
O script que gera a página de erros chama-se v-erreurs2.php. O seu código é o seguinte:
Les erreurs suivantes se sont produites :
<ul>
<?php
for($i=0;$i<count($dReponse["erreurs"]);$i++){
echo "<li class='erreur'>".$dReponse["erreurs"][$i]."</li>\n";
}//para
?>
</ul>
<div class="info"><?php echo $dReponse["info"] ?></div>
As partes dinâmicas desta vista, a definir pelo gerador de vistas, estão associadas às seguintes chaves do dicionário $dReponse:
- erros: tabela de mensagens de erro
- info: mensagem informativa
4.16.4. A folha de estilo
Não sofreu alterações. Continua a ser style1.css.
4.16.5. O novo ficheiro de configuração
Para introduzir estas novas vistas, temos de alterar algumas linhas do ficheiro de configuração.
<?php
// configuração do PHP
ini_set("register_globals","off");
ini_set("display_errors","off");
ini_set("expose_php","off");
// lista de módulos a incluir
$dConfig['includes']=array('c-impots-data.php','c-impots-calcul.php');
// controlador da aplicação
$dConfig['webapp']=array('titre'=>"Calculez votre impôt");
// configuração das vistas da aplicação
$dConfig['vuesReponse']['modele1']=array('url'=>'m-reponse.php');
$dConfig['vuesReponse']['modele2']=array('url'=>'m-reponse2.php');
$dConfig['vues']['formulaire']=array('url'=>'v-formulaire.php');
$dConfig['vues']['erreurs']=array('url'=>'v-erreurs.php');
$dConfig['vues']['formulaire2']=array('url'=>'v-formulaire2.php');
$dConfig['vues']['erreurs2']=array('url'=>'v-erreurs2.php');
$dConfig['vues']['bandeau']=array('url'=>'v-bandeau.php');
$dConfig['vues']['menu']=array('url'=>'v-menu.php');
$dConfig['style']['url']='style1.css';
// configuração das ações da aplicação
$dConfig['actions']['get:init']=array('url'=>'a-init.php');
$dConfig['actions']['post:calculerimpot']=array('url'=>'a-calculimpot.php');
$dConfig['actions']['get:retourformulaire']=array('url'=>'a-retourformulaire.php');
$dConfig['actions']['post:effacerformulaire']=array('url'=>'a-init.php');
$dConfig['actions']['enchainementinvalide']=array('url'=>'a-enchainementinvalide.php');
$dConfig['actions']['actionInvalide']=array('url'=>'a-actioninvalide.php');
// configuração dos relatórios da aplicação
$dConfig['etats']['e-formulaire']=array(
'actionsautorisees'=>array('post:calculerimpot','get:init','post:effacerformulaire'),
'vue'=>'e-formulaire2.php');
$dConfig['etats']['e-erreurs']=array(
'actionsautorisees'=>array('get:retourformulaire','get:init'),
'vue'=>'e-erreurs2.php');
$dConfig['etats']['sansetat']=array('actionsautorisees'=>array('get:init'));
// configuração do modelo da aplicação
$dConfig["DSN"]=array(
"sgbd"=>"mysql",
"user"=>"seldbimpots",
"mdp"=>"mdpseldbimpots",
"host"=>"localhost",
"database"=>"dbimpots"
);
?>
A alteração essencial consiste em substituir os geradores de visualização associados aos relatórios [e-formulaire] e [e-erreurs]. Feito isto, os novos geradores de visualização ficam encarregues de gerar as novas páginas de resposta.
4.16.6. O gerador de visualização associado ao relatório [e-formulaire]
No ficheiro de configuração, o estado [e-formulaire] está agora associado ao gerador de visualização e-formulaire2.php. O código deste script é o seguinte:
<?php
// prepara-se a resposta do formulário
$dReponse['titre']=$dConfig['webapp']['titre'];
$dReponse['vuereponse']='modele2';
$dReponse['vue1']=$dConfig['vues']['bandeau']['url'];
$dReponse['vue2']=$dConfig['vues']['menu']['url'];
$dReponse['vue3']=$dConfig['vues']['formulaire2']['url'];
$dReponse['urlstyle']=$dConfig['style']['url'];
$dReponse['titre']=$dConfig['webapp']['titre'];
$dReponse['liens']=array(
array('texte'=>'Réinitialiser le formulaire', 'url'=>'main.php?action=init')
);
// configuração de acordo com o tipo de formulário a gerar
$type=$dSession['etat']['secondaire'];
if($type=='init'){
// formulário vazio
$dReponse['optnon']='checked';
}//if
if($type=='calculimpot'){
// é necessário voltar a apresentar os parâmetros de introdução de dados armazenados na consulta
$dReponse['optoui']=$_POST['optmarie']=='oui' ? 'checked' : '';
$dReponse['optnon']=$dReponse['optoui'] ? '' : 'checked';
$dReponse['enfants']=$_POST['txtenfants'];
$dReponse['salaire']=$_POST['txtsalaire'];
$dReponse['resultat']='Impôt à payer : '.$dReponse['impot'].' F';
}//if
if($type=='retourformulaire'){
// é necessário voltar a apresentar os parâmetros de entrada armazenados na sessão
$dReponse['optoui']=$dSession['requete']['optmarie']=='oui' ? 'checked' : '';
$dReponse['optnon']=$dReponse['optoui']=='' ? 'checked' : '';
$dReponse['enfants']=$dSession['requete']['txtenfants'];
$dReponse['salaire']=$dSession['requete']['txtsalaire'];
}//if
// envia-se a resposta
finSession($dConfig,$dReponse,$dSession);
?>
As principais alterações são as seguintes:
- o gerador de visualizações indica que pretende utilizar o modelo de resposta «modele2»
- por esse motivo, preenche os elementos dinâmicos $dReponse['vue1'], $dReponse['vue2'], $dReponse['vue3'], sendo os três necessários para o modelo de resposta «modele2».
- O gerador preenche também o elemento dinâmico $dReponse['liens'], que define os links a apresentar na área [vue2] da resposta.
4.16.7. O gerador de visualização associado ao relatório [e-erreurs]
No ficheiro de configuração, o relatório [e-erreurs] está agora associado ao gerador de visualização e-erreurs2.php. O código deste script é o seguinte:
<?php
// preparamos a resposta de erros
$dReponse['titre']=$dConfig['webapp']['titre'];
$dReponse['vuereponse']='modele2';
$dReponse['vue1']=$dConfig['vues']['bandeau']['url'];
$dReponse['vue2']=$dConfig['vues']['menu']['url'];
$dReponse['vue3']=$dConfig['vues']['erreurs2']['url'];
$dReponse['urlstyle']=$dConfig['style']['url'];
$dReponse['titre']=$dConfig['webapp']['titre'];
$dReponse['liens']=array(
array('texte'=>'Retour au formulaire de saisie', 'url'=>'main.php?action=retourformulaire')
);
// informações adicionais
$type=$dSession['etat']['secondaire'];
if($type=='database'){
$dReponse['info']="Veuillez avertir l'administrateur de l'application";
}
// envia-se a resposta
finSession($dConfig,$dReponse,$dSession);
?>
As alterações introduzidas são idênticas às introduzidas no gerador de visualização e-formulaire2.php.
4.17. Conclusão
Conseguimos demonstrar, através de um exemplo, a vantagem do nosso controlador genérico. Não foi necessário escrevê-lo. Limitámo-nos a escrever os scripts das ações, dos geradores de visualização e das visualizações da aplicação. Além disso, demonstrámos a vantagem de separar as ações das visualizações. Assim, conseguimos alterar o aspeto das respostas sem modificar uma única linha de código dos scripts de ação. Apenas os scripts envolvidos na geração das vistas foram alterados. Para que isto seja possível, o script de ação não deve fazer qualquer suposição sobre a vista que irá apresentar as informações que calculou. Deve limitar-se a entregar essas informações ao controlador, que as transmite ao gerador de vistas, o qual lhes dará formato. Esta é uma regra absoluta: uma ação deve estar completamente separada das vistas.
Neste capítulo, abordámos a filosofia Struts, bem conhecida dos programadores Java. Um projeto «open source» denominado php.mvc permite realizar desenvolvimento web/PHP com a filosofia Struts. Consulte o site http://www.phpmvc.net/ para mais informações.













