4. Um exemplo prático
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 seu salário para declarar:
- calcula-se o número de cotas do empregado nbParts = nbEnfants/2 + 1 se ele for solteiro, nbEnfants/2 + 2 se for casado, onde nbEnfants é o número de filhos. O número de faixas é aumentado em 0,5 se houver três filhos ou mais.
- calcula-se sua renda tributável R = 0,72 * S, onde S é seu salário anual
- calcula-se seu coeficiente familiar Q = R/N
- calcula-se seu imposto I com base nos seguintes dados
| Cada linha possui três 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 resulta no imposto I = 0,65*R - 49062*nbParts. |
4.2. O banco de dados
Os dados anteriores são registrados em um banco de dados MySQL chamado dbimpots. O usuário seldbimpots, com a senha mdpseldbimpots, tem acesso somente para leitura ao conteúdo do banco de dados. Este possui uma única tabela chamada impots, cuja estrutura é a seguinte:

Seu conteúdo é o seguinte:

4.3. A arquitetura MVC do aplicativo
A aplicação terá a seguinte arquitetura MVC:
![]() |
- o controlador main.php será o controlador genérico apresentado anteriormente
- a solicitação do cliente é enviada ao controlador na forma de uma requisiçã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 retorna ao controlador uma variável indicando o estado em que a aplicação web deve ser colocada. Com esse estado, o controlador ativará um dos geradores de visualizações para enviar a resposta ao cliente.
- impots-data.php é a classe responsável por fornecer ao controlador os dados de que ele necessita
- impots-calcul.php é a classe de negócios que permite o cálculo do imposto
4.4. A classe de acesso aos dados
A classe de acesso aos dados foi criada para ocultar da aplicação web a origem dos dados. Em sua interface, encontramos um método getData que fornece os três tabuletos de dados necessários para o cálculo do imposto. Em nosso exemplo, os dados são extraídos de um banco 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 conexão
var $sDatabase; // nome do banco de dados
var $oDB; // conexão com o banco de dados
var $aErreurs; // lista de erros
var $oRésultats; // resultado de uma consulta
var $connecté; // valor booleano que indica se há ou não conexão com o banco de dados
var $sQuery; // a última consulta executada
// construtor
function impots_data($dDSN){
// $dDSN: dicionário que define a conexão a ser estabelecida
// $dDSN['sgbd']: o tipo do SGBD ao qual é necessário se conectar
// $dDSN['host']: o nome do servidor que o hospeda
// $dDSN['database']: o nome do banco de dados ao qual é necessário se conectar
// $dDSN['user']: um usuário do banco de dados
// $dDSN['mdp']: sua senha
// cria em $oDB uma conexão com o banco de dados definido por $dDSN sob a identidade de $dDSN['user']
// se a conexão for bem-sucedida
// insere em $sDSN a string de conexão com o banco de dados
// armazena em $sDataBase o nome do banco de dados ao qual se está conectando
// define $connecté como verdadeiro
// se a conexão falhar
// insere as mensagens de erro adequadas na lista $aErreurs
// encerra a conexão, se necessário
// define $connecté como falso
// limpa a lista de erros
$this->aErreurs=array();
// cria-se uma conexão com o banco de dados $sDSN
$this->sDSN=$dDSN["sgbd"]."://".$dDSN["user"].":".$dDSN["mdp"]."@".$dDSN["host"]."/".$dDSN["database"];
$this->sDatabase=$dDSN["database"];
$this->connect();
// conectado?
if( ! $this->connecté) return;
// a conexão foi bem-sucedida
$this->connecté=TRUE;
}//criador
// ------------------------------------------------------------------
function connect(){
// (re)conexão com o banco de dados
// limpar lista de erros
$this->aErreurs=array();
// estamos criando uma conexão com o banco de dados $sDSN
$this->oDB=DB::connect($this->sDSN,true);
// erro?
if(DB::iserror($this->oDB)){
// registro do erro
$this->aErreurs[]="Echec de la connexion à la base [".$this->sDatabase."] : [".$this->oDB->getMessage()."]";
// a conexão falhou
$this->connecté=FALSE;
// fim
return;
}
// estamos conectados
$this->connecté=TRUE;
}//conectar
// ------------------------------------------------------------------
function disconnect(){
// se estiver conectado, encerra-se a conexão com a base $sDSN
if($this->connecté){
$this->oDB->disconnect();
// estamos desconectados
$this->connecté=FALSE;
}//se
}//desconectar
// -------------------------------------------------------------------
function execute($sQuery){
// $sQuery: consulta a ser executada
// a consulta está sendo armazenada
$this->sQuery=$sQuery;
// estamos conectados?
if(! $this->connecté){
// registrando 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)){
// registra-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 da 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
// desconectando
$oImpots->disconnect();
// acompanhamento
echo "Déconnecté de la base...\n";
// fim
exit(0);
// ----------------------------------
function checkErreurs(&$oImpots){
// erros?
if(count($oImpots->aErreurs)!=0){
// exibição
for($i=0;$i<count($oImpots->aErreurs);$i++){
echo $oImpots->aErreurs[$i]."\n";
}//para
// erros
return true;
}//se
// 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
Essa classe permite calcular o imposto de um contribuinte. São fornecidos ao seu construtor os dados necessários para esse cálculo. Em seguida, ele se encarrega 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 indicando 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 renda
// coeficientes: tabela dos coeficientes de renda
// coeffn: tabela dos coeficientes do número de cotas
// as três tabelas têm o mesmo número de elementos
// cálculo do número de cotas
if($perso['marié'])
$nbParts=$perso['enfants']/2+2;
else $nbParts=$perso['enfants']/2+1;
if ($perso['enfants']>=3) $nbParts+=0.5;
// renda tributável
$revenu=0.72*$perso['salaire'];
// quociente familiar
$QF=$revenu/$nbParts;
// busca 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 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)){
exit(0);
}
// desconectando
$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){
// exibição
for($i=0;$i<count($oImpots->aErreurs);$i++){
echo $oImpots->aErreurs[$i]."\n";
}//para
// erros
return true;
}//se
// 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 do aplicativo
Ao iniciar o aplicativo web de cálculo de impostos, é exibida a seguinte tela [v-formulaire]:
![]() |
O usuário preenche os campos e solicita o cálculo do imposto:
![]() |
Observe-se que o formulário é regenerado no estado em que o usuário o validou e que, além disso, exibe o valor do imposto a pagar. O usuário pode cometer erros de digitação. Esses erros são sinalizados por meio de uma página de erros, que chamaremos de tela [v-erreurs].
![]() |
![]() |
O link [Retour au formulaire de saisie] permite que o usuário recupere o formulário exatamente como o validou.
![]() |
Por fim, o botão [Effacer le formulaire] reverte o formulário ao seu estado inicial, c.a.d, tal como o usuário o recebeu na solicitação inicial.
4.7. Análise da arquitetura MVC do aplicativo
A aplicação possui a seguinte arquitetura MVC:
![]() |
Acabamos de descrever as duas classes impots-data.php e impots-calcul.php. Passaremos agora a descrever os demais elementos da arquitetura.
4.8. O controlador da aplicação
O controlador main.php da aplicação é aquele 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 ser realizada
$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 deveríamos chegar até 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
// registro da sessão
if(isset($dSession)){
//: os parâmetros da solicitação são inseridos 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 do aplicativo web
Existem quatro ações:
- get:init: é a ação acionada durante a solicitação inicial sem parâmetros ao controlador. Ela gera a visualização “formulário” vazia.
- post:effacerformulaire: ação acionada pelo botão [Effacer le formulaire]. Ela gera a visualização [v-formulaire] vazia.
- post:calculerimpot: ação acionada pelo botão [Calculer l'impôt]. Ela gera a visualização [v-formulaire] com o valor do imposto a pagar ou a visualização [v-erreurs].
- get:retourformulaire: ação acionada pelo link [Retour au formulaire de saisie]. Ela gera a visualização [v-formulaire] pré-preenchida com os dados incorretos.
Essas ações são configuradas da seguinte maneira no arquivo de configuração:
<?php
…
// configuração das ações do aplicativo
$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 por processá-la. Cada ação levará o aplicativo web a um estado definido pelo elemento $dSession['etat']['principal']. Esse estado deve ser salvo na sessão. Além disso, a ação registra no dicionário $dReponse as informações necessárias para a exibição da visualização associada ao novo estado em que a aplicação se encontrará.
4.10. Os relatórios do aplicativo web
Existem dois:
- [e-formulaire]: relatório no qual são apresentadas as diferentes variantes da visualização [v-formulaire].
- [e-erreurs]: estado em que é apresentada a visualização [v-erreurs].
As ações permitidas nesses estados são as seguintes:
<?php
…
// configuração dos estados do aplicativo
$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'));
Em um estado, as ações autorizadas correspondem aos destinos URL dos links ou botões [submit] da visualização associada ao estado. Além disso, a ação 'get:init' está sempre autorizada. Isso permite que o usuário recupere o URL main.php da lista de URL do seu navegador e o reproduza novamente, independentemente do estado do aplicativo. Trata-se de uma espécie de reinicialização “manual”. O estado “sem estado” existe apenas na inicialização do aplicativo.
A cada estado do aplicativo está associado um script responsável por gerar a visualização correspondente ao estado:
- estado [e-formulaire]: script e-formulaire.php
- relatório [e-erreurs]: script e-erreurs.php
O relatório [e-formulaire] apresentará a visualização [v-formulaire] com variantes. De fato, a visualização [v-formulaire] pode ser apresentada vazia, pré-preenchida ou com o valor do imposto. A ação que levará o aplicativo ao relatório [e-formulaire] especifica, na variável $dSession['etat']['principal'], o relatório principal do aplicativo. O controlador utiliza apenas essa informação. Em nosso aplicativo, a ação que leva ao estado [e-formulaire] adicionará em $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 valor do imposto. Poderíamos ter procedido de maneira diferente, considerando que haviam ali três estados diferentes e, portanto, três geradores de visualização a serem escritos.
4.11. O arquivo 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 serem incluídos
$dConfig['includes']=array('c-impots-data.php','c-impots-calcul.php');
// controlador do aplicativo
$dConfig['webapp']=array('titre'=>"Calculez votre impôt");
// configuração das visualizações 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 do aplicativo
$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 do aplicativo
$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 do aplicativo 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. Esse estado deve ser indicado em $dSession['etat']['principal'].
- Um script de ação pode precisar inserir informações na sessão. Para isso, ele as insere no dicionário $dSession, sendo que esse dicionário é automaticamente salvo na sessão pelo controlador ao final do ciclo de solicitação-resposta.
- Um script de ação pode ter informações a serem passadas para as visualizações. Esse aspecto é independente do controlador. Trata-se da interface entre as ações e as visualizações, interface específica de cada aplicação. No exemplo analisado aqui, as ações fornecerão informações aos geradores de visualizações por meio de um dicionário chamado $dReponse.
4.12.2. A ação get:init
Essa é a ação que gera o formulário vazio. O arquivo de configuração mostra que ela será processada pelo script a-init.php:
O código do script a-init.php é o seguinte:
<?php
// exibe-se o formulário de preenchimento
$dSession['etat']=array('principal'=>'e-formulaire', 'secondaire'=>'init');
?>
Este script se limita a definir, em $dSession['etat']['principal'], o estado em que o aplicativo deve se encontrar, o estado [e-formulaire], e fornece em $dSession['etat']['secondaire'] uma especificação sobre esse estado. O arquivo de configuração nos mostra 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 gerará a visualização [v-formulaire] em suas variantes [init] e c.a.d. O formulário estará vazio.
4.12.3. A ação post:calculerimpot
Essa é a ação que permite calcular o imposto a partir dos dados inseridos no formulário. O arquivo de configuração indica que é o script a-calculimpot.php que processará essa ação:
O código do script a-calculimpot.php é o seguinte:
<?php
// solicitação de cálculo de imposto
// primeiro verifica-se 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 é encerrado
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 inseridos estiverem corretos
// recuperam-se os dados necessários para o cálculo do imposto
if(! $dSession['limites']){
// os dados não estão na sessão
// eles são recuperados da fonte de dados
list($erreurs,$limites,$coeffr,$coeffn)=getData($dConfig['DSN']);
// se houver erros, exibe-se 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 inseridos 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
// calculamos 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){
// conexão com a 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();
// desconexão
$oImpots->disconnect();
// retornando o resultado
if(count($oImpots->aErreurs)!=0) return array($oImpots->aErreurs);
else return array(array(),$limites,$coeffr,$coeffn);
}//getData
O script faz o que deve fazer: calcular o imposto. Deixamos a cargo do leitor a tarefa de interpretar o código do processamento. Nosso foco está nos estados que podem ocorrer em decorrência dessa ação:
- os dados inseridos estão incorretos ou o acesso aos dados falha: o aplicativo é colocado no estado [e-erreurs]. O arquivo de configuração mostra que é o script e-erreurs.php que será responsável por gerar a visualização de resposta:
<?php
…
$dConfig['etats']['e-erreurs']=array(
'actionsautorisees'=>array('get:retourformulaire','get:init'),
'vue'=>'e-erreurs.php');
- em todos os outros casos, o aplicativo é colocado no estado [e-formulaire] com a variante de cálculo de impostos indicada em $dSession['etat']['secondaire']. O arquivo de configuração mostra que é o script e-formulaire.php que irá gerar a visualização da resposta. Ele utilizará o valor de $dSession['etat']['secondaire'] para gerar um formulário pré-preenchido com os valores inseridos pelo usuário e, além disso, o valor do imposto.
4.12.4. A ação post:effacerformulaire
Ela está associada, por configuração, ao script a-init.php já descrito.
4.12.5. A ação get:retourformulaire
Ela permite retornar ao estado [e-formulaire] a partir do estado [e-erreurs]. O script a-retourformulaire.php é responsável por processar essa ação:
O script a-retourformulaire.php é o seguinte:
<?php
// exibe-se o formulário de entrada
$dSession['etat']=array('principal'=>'e-formulaire','secondaire'=>'retourformulaire');
?>
Basta solicitar que o aplicativo seja colocado no estado [e-formulaire], em sua variante [retourformulaire]. O arquivo de configuração nos mostra 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 gerará a visualização [v-formulaire] em suas variantes [retourformulaire] e c.a.d. o formulário pré-preenchido com os valores inseridos pelo usuário, mas sem o valor do imposto.
4.13. Sequência de ações inválida
As ações válidas a partir de um determinado estado do aplicativo são definidas por configuração:
<?php
…
// configuração dos estados do aplicativo
$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á explicamos essa configuração. Se for detectada uma sequência inválida de ações, o script a-enchainementinvalide.php é executado:
O código desse 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 o aplicativo 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 desse gerador mais adiante. A visualização enviada ao cliente é a seguinte:

4.14. As visualizações do aplicativo
4.14.1. Exibição da visualização final
Vamos ver como o controlador envia a resposta ao cliente, uma vez executada a ação solicitada por ele:
<?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 ser realizada
$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
// registro da sessão
...
//: envio da resposta ao cliente
include $dConfig['vuesReponse'][$dReponse['vuereponse']]['url'];
// fim do script
exit(0);
}//fim da sessão
Ao retornar de um script de ação, o controlador recupera em $dSession['etat']['principal'] o estado no qual deve colocar o aplicativo. Esse estado foi definido pela ação que acabou de ser executada. O controlador então executa o gerador de visualização associado ao estado. Ele encontra o nome deste no arquivo de configuração. A função do gerador de visualização é a seguinte:
- define em $dReponse['vuereponse'] o nome do modelo de resposta a ser utilizado. Essa informação será passada ao controlador. Um modelo é uma composição de visões elementares que, juntas, formam a visão final.
- prepara as informações dinâmicas a serem exibidas na visualização final. Esse ponto é independente do controlador. Trata-se da interface entre o gerador de visualizações e a visualização final. Ela é específica para cada aplicação.
- deve terminar obrigatoriamente com a chamada à função finSession do controlador. Essa função irá
- salvar 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
// registro 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 usuário é definida pela entidade $dReponse['vuereponse'], que define o modelo a ser utilizado para a resposta final.
4.14.2. Modelo da resposta
O aplicativo gerará suas diferentes respostas de acordo com o seguinte modelo único:
![]() |
Este modelo está associado à chave “modelo1” 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 possui três elementos dinâmicos inseridos em um 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 visualização vue1
- vue2: nome do script responsável por gerar a visualização vue2
Um gerador de visualização que deseje utilizar o modelo modelo1 deverá definir esses três elementos dinâmicos. Definiremos agora as visualizações 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 área [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 inseridos em um dicionário $dReponse e associados às seguintes chaves:
- título: título a ser exibido
- resultado: valor do imposto a pagar
4.14.4. A visualização elementar v-formulaire.php
A parte [vue2] corresponde à visualização [v-formulaire] ou à visualização [v-erreurs]. A visão [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 visualização, que deverão ser definidas pelo gerador de visualização, estão associadas às seguintes chaves do dicionário $dReponse:
- optoui: estado do botão de opção chamado optoui
- optnon: estado do botão de opção chamado optnon
- filhos: número de filhos a ser inserido no campo txtenfants
- salário: salário anual a ser inserido no campo txtsalário
4.14.5. A visualização elementar v-erreurs.php
A visualização [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 visão, a serem definidas pelo gerador de visões, estão associadas às seguintes chaves do dicionário $dReponse:
- erros: tabela de mensagens de erro
- info: mensagem informativa
- link: texto de um link
- href: URL de destino do link acima
4.14.6. A folha de estilo
Todas as visualizações são “estilizadas” por uma folha de estilo. Para alterar a aparência visual do aplicativo, é preciso modificar 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. Geradores de visualizações
4.15.1. Função de um gerador de visualização
Vamos relembrar 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 visualização está vinculado ao estado no qual o aplicativo será colocado. A ligação entre o estado e o gerador de visualização é definida por meio da configuração:
<?php
…
// configuração dos estados do aplicativo
$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á explicamos qual é 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 ser utilizado. Essa informação será passada ao controlador. Um modelo é uma composição de visões elementares que, juntas, formam a visão final.
- prepara as informações dinâmicas a serem exibidas na visualização final. Esse ponto é independente do controlador. Trata-se da interface entre o gerador de visualizações e a visualização final. Ela é específica para cada aplicação.
- deve terminar obrigatoriamente com a chamada à função finSession do controlador. Essa função irá
- salvar a sessão
- enviar a resposta
4.15.2. O gerador de visualização associado ao relatório [e-formulaire]
O script responsável por gerar a visualização associada ao relatório [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');
Seu código é o seguinte:
<?php
// preparação da 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 ser gerado
$type=$dSession['etat']['secondaire'];
if($type=='init'){
// formulário vazio
$dReponse['optnon']='checked';
}//if
if($type=='calculimpot'){
// é necessário exibir novamente os parâmetros de entrada 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'){
// precisamos exibir novamente 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
// enviamos a resposta
finSession($dConfig,$dReponse,$dSession);
?>
Observe-se que o gerador de visualização cumpre as condições exigidas para um gerador de visualização:
- definir em $dReponse['vuereponse'] o modelo de resposta a ser utilizado
- passar informações para esse modelo. Aqui, elas são passadas por meio 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 necessárias para esse modelo: $dReponse['vue1'] e $dReponse['vue2'].
No caso específico de nossa aplicação, a visualização 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 maneira. Além disso, aqui todas as informações necessárias para a exibição da visualização final são colocadas no dicionário $dReponse. Mais uma vez, essa é uma escolha que cabe ao desenvolvedor. O estado [e-formulaire] pode ocorrer após quatro ações diferentes: init, calcularimposto, retornarformulário, apagarformulário. A visualização a ser exibida não é exatamente a mesma em todos os casos. Por isso, distinguimos aqui três casos em $dSession['etat']['secondaire']:
- init: o formulário é exibido vazio
- cálculo do imposto: o formulário é exibido com o valor do imposto e os dados que levaram ao seu cálculo
- retourformulaire: o formulário é exibido com os dados inseridos inicialmente
Acima, o script e-formulaire.php utiliza essas informações para apresentar a resposta de acordo com essas três variantes.
4.15.3. A visualização associada ao relatório [e-erreurs]
O script responsável por gerar a visualização 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 complementares
$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 visualização final
Os dois scripts que geram as duas visualizações finais terminam 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 usuário é definida pela entidade $dReponse['vuereponse'], que define o modelo a ser utilizado para a resposta final. Para os relatórios [e-formulaire] e [e-erreurs], esse modelo foi definido como igual a modele1:
Esse modelo corresponde, por configuração, ao script m-reponse.php:
4.16. Modificar o modelo de resposta
Supomos aqui que se decida alterar a aparência visual da resposta enviada ao cliente e nos interessamos em compreender as repercussões que isso acarreta no código.
4.16.1. O novo modelo
A estrutura da resposta será agora a seguinte:
![]() |
Esse modelo será chamado de modele2 e o script responsável por gerá-lo será chamado de 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 ser utilizada
- $dReponse['vue1']: o script a ser utilizado para gerar [vue1]
- $dReponse['vue2']: o script a ser usado para gerar [vue2]
- $dReponse['vue3']: o script a ser utilizado para gerar [vue3]
Esses elementos deverão ser definidos pelos geradores de visualizações.
4.16.2. As diferentes páginas de resposta
A aplicação passará a apresentar as seguintes respostas ao usuário. Na chamada inicial, a página de resposta será a seguinte:
![]() |
Se o usuário fornecer dados válidos, o imposto será calculado:
![]() |
Caso cometa erros na digitação, a página de erros será exibida:
![]() |
Se ele utilizar o link [Retour au formulaire de saisie], ele voltará ao formulário exatamente como o validou:
![]() |
Se, no exemplo acima, ele usar o link [Réinitialiser le formulaire], ele encontrará um formulário vazio:
![]() |
Observe-se que o aplicativo utiliza, de fato, as mesmas ações de antes. Apenas a aparência das respostas mudou.
4.16.3. As visualizações básicas
A visualização elementar [vue1] será, assim 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 visualização possui dois elementos dinâmicos:
- $dReponse['titre']: título a ser exibido
- $dReponse['resultat']: valor do imposto a pagar
A visualização 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 visualização possui os seguintes elementos dinâmicos:
- $dReponse['liens']: tabela de links a serem exibidos em [vue2]. Cada elemento da tabela é um dicionário com duas chaves:
- 'url': URL de destino do link
- 'texto': texto do link
A visualização elementar [vue3] será associada ao script v-formulaire2.php se quisermos exibir o formulário de preenchimento ou ao script v-erreurs2.php se quisermos exibir 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 visualização, que deverão ser definidas pelo gerador de visualização, estão associadas às seguintes chaves do dicionário $dReponse:
- optoui: estado do botão de opção chamado optoui
- optnon: estado do botão de opção chamado optnon
- filhos: número de filhos a ser inserido no campo txtenfants
- salário: salário anual a ser inserido no campo txtsalário
O script que gera a página de erros chama-se v-erreurs2.php. 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 visão, a serem definidas pelo gerador de visões, 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
Ela não sofreu alterações. Continua sendo style1.css.
4.16.5. O novo arquivo de configuração
Para implementar essas novas visualizações, precisamos alterar algumas linhas do arquivo 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 serem incluídos
$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 visualizações 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 do aplicativo
$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 do aplicativo
$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 principal consiste em trocar os geradores de visualização associados aos relatórios [e-formulaire] e [e-erreurs]. Feito isso, os novos geradores de visualização ficam encarregados de gerar as novas páginas de resposta.
4.16.6. O gerador de visualização associado ao relatório [e-formulaire]
No arquivo de configuração, o relatório [e-formulaire] agora está associado ao gerador de visualização e-formulaire2.php. O código desse 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 ser gerado
$type=$dSession['etat']['secondaire'];
if($type=='init'){
// formulário vazio
$dReponse['optnon']='checked';
}//if
if($type=='calculimpot'){
// é necessário exibir novamente os parâmetros de entrada 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'){
// precisamos exibir novamente 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
// enviamos a resposta
finSession($dConfig,$dReponse,$dSession);
?>
As principais alterações são as seguintes:
- o gerador de visualização indica que deseja utilizar o modelo de resposta modele2
- por esse motivo, ele preenche os elementos dinâmicos $dReponse['vue1'], $dReponse['vue2'], $dReponse['vue3'] — todos os três necessários para o modelo de resposta modele2.
- O gerador também preenche o elemento dinâmico $dReponse['liens'], que define os links a serem exibidos na área [vue2] da resposta.
4.16.7. O gerador de visualização associado ao relatório [e-erreurs]
No arquivo de configuração, o relatório [e-erreurs] agora está associado ao gerador de visualização e-erreurs2.php. O código desse 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 complementares
$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 feitas são idênticas às realizadas no gerador de visualização e-formulaire2.php.
4.17. Conclusão
Conseguimos demonstrar, por meio de um exemplo, a vantagem do nosso controlador genérico. Não precisamos escrevê-lo. Limitamo-nos a escrever os scripts das ações, dos geradores de visualização e das visualizações do aplicativo. Além disso, demonstramos a vantagem de separar as ações das visualizações. Assim, pudemos alterar a aparência das respostas sem modificar uma única linha de código dos scripts de ação. Apenas os scripts envolvidos na geração das visualizações foram modificados. Para que isso seja possível, o script de ação não deve fazer nenhuma suposição sobre a visualização que exibirá as informações que ele calculou. Ele deve se limitar a entregar essas informações ao controlador, que as transmite ao gerador de visualização, o qual as formatará. Essa é uma regra absoluta: uma ação deve estar completamente separada das visualizações.
Neste capítulo, abordamos a filosofia Struts, bem conhecida pelos desenvolvedores Java. Um projeto de código aberto chamado php.mvc permite o desenvolvimento web/PHP com a filosofia Struts. Consulte o site http://www.phpmvc.net/ para obter mais informações.













