4. Una aplicación de ejemplo
Nos proponemos ilustrar el método anterior con un ejemplo de cálculo de impuestos.
4.1. El problema
Nos proponemos escribir un programa que permita calcular el impuesto de un contribuyente. Consideramos el caso simplificado de un contribuyente que solo tiene que declarar su salario:
- se calcula el número de cuotas del empleado nbParts = nbEnfants/2 + 1 si no está casado, nbEnfants/2+2 si está casado, donde nbEnfants es su número de hijos. El número de partes se incrementa en 0,5 si hay tres hijos o más.
- Se calcula su ingreso imponible R = 0,72 * S, donde S es su salario anual
- se calcula su coeficiente familiar Q = R/N
- se calcula su impuesto I según los siguientes datos
| Cada línea tiene tres campos límite: coeffR, coeffN. Para calcular el impuesto I, se busca la primera línea en la que QF sea menor o igual al límite. Por ejemplo, si QF = 30000, se encontrará la línea: 31810 0,2 3309.5. El impuesto I es entonces igual a 0.2*R - 3309.5*nbParts. Si QF es tal que la relación QF <= límite nunca se cumple, entonces se utilizan los coeficientes de la última línea: 0 0.65 49062, lo que da como resultado el impuesto I = 0.65*R - 49062*nbParts. |
4.2. La base de datos
Los datos anteriores se registran en una base de datos MySQL llamada dbimpots. El usuario seldbimpots, con contraseña mdpseldbimpots, tiene acceso de solo lectura al contenido de la base de datos. Esta cuenta con una única tabla llamada impots, cuya estructura es la siguiente:

Su contenido es el siguiente:

4.3. La arquitectura MVC de la aplicación
La aplicación tendrá la siguiente arquitectura MVC:
![]() |
- El controlador main.php será el controlador genérico presentado anteriormente
- La solicitud del cliente se envía al controlador en forma de una consulta con el formato main.php?action=xx. El valor del parámetro «action» determina el script del bloque ACTIONS que se debe ejecutar. El script de acción ejecutado devuelve al controlador una variable que indica el estado en el que debe colocarse la aplicación web. Con este estado, el controlador activará uno de los generadores de vistas para enviar la respuesta al cliente.
- impots-data.php es la clase encargada de proporcionar al controlador los datos que necesita
- impots-calcul.php es la clase de negocio que permite calcular el impuesto
4.4. La clase de acceso a datos
La clase de acceso a datos está diseñada para ocultar a la aplicación web el origen de los datos. En su interfaz, se encuentra un método getData que proporciona los tres tableros de datos necesarios para el cálculo del impuesto. En nuestro ejemplo, los datos se obtienen de una base de datos MySQL. Para que la clase sea independiente del tipo real de SGBD, utilizaremos la biblioteca pear::DB descrita en el anexo. El código de la clase es el siguiente:
<?php
// bibliotecas
require_once 'DB.php';
class impots_data{
// clase de acceso a la fuente de datos DBIMPOTS
// atributos
var $sDSN; // la cadena de conexión
var $sDatabase; // el nombre de la base de datos
var $oDB; // conexión a la base de datos
var $aErreurs; // lista de errores
var $oRésultats; // resultado de una consulta
var $connecté; // valor booleano que indica si se está conectado o no a la base de datos
var $sQuery; // la última consulta ejecutada
// constructor
function impots_data($dDSN){
// $dDSN: diccionario que define la conexión que se debe establecer
// $dDSN['sgbd']: el tipo de SGBD al que hay que conectarse
// $dDSN['host']: el nombre de la máquina host que lo aloja
// $dDSN['database']: el nombre de la base de datos a la que hay que conectarse
// $dDSN['user']: un usuario de la base de datos
// $dDSN['mdp']: su contraseña
// crea en $oDB una conexión a la base de datos definida por $dDSN con la identidad de $dDSN['user']
// si la conexión se realiza con éxito
// almacena en $sDSN la cadena de conexión a la base de datos
// asigna a $sDataBase el nombre de la base de datos a la que nos conectamos
// establece $connecté como verdadero
// si falla la conexión
// agrega los mensajes de error correspondientes a la lista $aErreurs
// cierra la conexión si es necesario
// establece $connecté en falso
// borra la lista de errores
$this->aErreurs=array();
// se crea una conexión a la base de datos $sDSN
$this->sDSN=$dDSN["sgbd"]."://".$dDSN["user"].":".$dDSN["mdp"]."@".$dDSN["host"]."/".$dDSN["database"];
$this->sDatabase=$dDSN["database"];
$this->connect();
// ¿Conectado?
if( ! $this->connecté) return;
// la conexión se realizó con éxito
$this->connecté=TRUE;
}//fabricante
// ------------------------------------------------------------------
function connect(){
// (re)conexión a la base
// borrar lista de errores
$this->aErreurs=array();
// se está creando una conexión con la base de datos $sDSN
$this->oDB=DB::connect($this->sDSN,true);
// ¿Error?
if(DB::iserror($this->oDB)){
// se registra el error
$this->aErreurs[]="Echec de la connexion à la base [".$this->sDatabase."] : [".$this->oDB->getMessage()."]";
// La conexión falló
$this->connecté=FALSE;
// fin
return;
}
// estamos conectados
$this->connecté=TRUE;
}//conectarse
// ------------------------------------------------------------------
function disconnect(){
// si estamos conectados, cerramos la conexión con la base $sDSN
if($this->connecté){
$this->oDB->disconnect();
// estamos desconectados
$this->connecté=FALSE;
}//si
}//desconectar
// -------------------------------------------------------------------
function execute($sQuery){
// $sQuery: consulta para ejecutar
// se almacena la consulta
$this->sQuery=$sQuery;
// ¿Estamos conectados?
if(! $this->connecté){
// se registra el error
$this->aErreurs[]="Pas de connexion existante à la base [$this->sDatabase]";
// fin
return;
}//si
// ejecución de la consulta
$this->oRésultats=$this->oDB->query($sQuery);
// ¿Error?
if(DB::iserror($this->oRésultats)){
// se registra el error
$this->aErreurs[]="Echec de la requête [$sQuery] : [".$this->oRésultats->getMessage()."]";
// regreso
return;
}//si
}//ejecutar
// ------------------------------------------------------------------
function getData(){
// se recuperan las 3 series de datos: límites, coeffr, coeffn
$this->execute('select limites, coeffR, coeffN from impots');
// ¿Hay errores?
if(count($this->aErreurs)!=0) return array();
// recorremos el resultado de la consulta
while ($ligne = $this->oRésultats->fetchRow(DB_FETCHMODE_ASSOC)) {
$limites[]=$ligne['limites'];
$coeffr[]=$ligne['coeffR'];
$coeffn[]=$ligne['coeffN'];
}//mientras
return array($limites,$coeffr,$coeffn);
}//getDataImpots
}//clase
?>
Un programa de prueba podría ser el siguiente:
<?php
// biblioteca
require_once "c-impots-data.php";
require_once "DB.php";
// prueba de la clase impots-data
ini_set('track_errors','on');
ini_set('display_errors','on');
// configuración básica de dbimpots
$dDSN=array(
"sgbd"=>"mysql",
"user"=>"seldbimpots",
"mdp"=>"mdpseldbimpots",
"host"=>"localhost",
"database"=>"dbimpots"
);
// inicio de sesión
$oImpots=new impots_data($dDSN);
// ¿Errores?
if(checkErreurs($oImpots)){
exit(0);
}
// seguimiento
echo "Connecté à la base...\n";
// recuperación de datos de límites, coeffr, coeffn
list($limites,$coeffr,$coeffn)=$oImpots->getData();
// ¿Errores?
if( ! checkErreurs($oImpots)){
// contenido
echo "données : \n";
for($i=0;$i<count($limites);$i++){
echo "[$limites[$i],$coeffr[$i],$coeffn[$i]]\n";
}//para
}//si
// se desconecta
$oImpots->disconnect();
// seguimiento
echo "Déconnecté de la base...\n";
// fin
exit(0);
// ----------------------------------
function checkErreurs(&$oImpots){
// ¿Hay errores?
if(count($oImpots->aErreurs)!=0){
// visualización
for($i=0;$i<count($oImpots->aErreurs);$i++){
echo $oImpots->aErreurs[$i]."\n";
}//para
// ¿Hay errores?
return true;
}//si
// sin errores
return false;
}//checkErreurs
?>
Al ejecutar este programa de prueba se obtienen los siguientes 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. La clase de cálculo del impuesto
Esta clase permite calcular el impuesto de un contribuyente. Se le proporcionan a su constructor los datos necesarios para realizar este cálculo. A continuación, se encarga de calcular el impuesto correspondiente. El código de la clase es el siguiente:
<?php
class impots_calcul{
// clase de cálculo del impuesto
// constructor
function impots_calcul(&$perso,&$data){
// $perso: diccionario con las siguientes claves
// hijos(a): número de hijos
// salario: salario anual
// casado(a): valor booleano que indica si el contribuyente está casado o no
// impuesto(s): impuesto a pagar calculado por este generador
// $data: diccionario con las siguientes claves
// límites: tabla de límites de tramos
// coeficientes: tabla de coeficientes de los ingresos
// coeffn: tabla de coeficientes del número de participaciones
//: las tres tablas tienen el mismo número de elementos
// cálculo del número de participaciones
if($perso['marié'])
$nbParts=$perso['enfants']/2+2;
else $nbParts=$perso['enfants']/2+1;
if ($perso['enfants']>=3) $nbParts+=0.5;
// ingresos imponibles
$revenu=0.72*$perso['salaire'];
// coeficiente familiar
$QF=$revenu/$nbParts;
// búsqueda del tramo impositivo correspondiente a QF
$nbTranches=count($data['limites']);
$i=0;
while($i<$nbTranches-2 && $QF>$data['limites'][$i]) $i++;
// el impuesto
$perso['impot']=floor($data['coeffr'][$i]*$revenu-$data['coeffn'][$i]*$nbParts);
}//constructor
}//clase
?>
Un programa de prueba podría ser el siguiente:
<?php
// biblioteca
require_once "c-impots-data.php";
require_once "c-impots-calcul.php";
// configuración básica de dbimpots
$dDSN=array(
"sgbd"=>"mysql",
"user"=>"seldbimpots",
"mdp"=>"mdpseldbimpots",
"host"=>"localhost",
"database"=>"dbimpots"
);
// inicio de sesión
$oImpots=new impots_data($dDSN);
// ¿Errores?
if(checkErreurs($oImpots)){
exit(0);
}
// seguimiento
echo "Connecté à la base...\n";
// recuperación de datos de límites, coeffr, coeffn
list($limites,$coeffr,$coeffn)=$oImpots->getData();
// ¿Errores?
if(checkErreurs($oImpots)){
exit(0);
}
// se desconecta
$oImpots->disconnect();
// seguimiento
echo "Déconnecté de la base...\n";
// cálculo de un impuesto
$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);
// fin
exit(0);
// ----------------------------------
function checkErreurs(&$oImpots){
// ¿Hay errores?
if(count($oImpots->aErreurs)!=0){
// visualización
for($i=0;$i<count($oImpots->aErreurs);$i++){
echo $oImpots->aErreurs[$i]."\n";
}//para
// ¿Hay errores?
return true;
}//si
// sin errores
return false;
}//checkErreurs
?>
Al ejecutar este programa de pruebas se obtienen los siguientes 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. Cómo funciona la aplicación
Al iniciar la aplicación web de cálculo de impuestos, aparece la siguiente vista [v-formulaire]:
![]() |
El usuario llena los campos y solicita el cálculo del impuesto:
![]() |
Cabe destacar que el formulario se regenera tal como lo validó el usuario y que, además, muestra el monto del impuesto a pagar. El usuario puede cometer errores al ingresar los datos. Estos se le señalan mediante una página de errores que llamaremos vista [v-erreurs].
![]() |
![]() |
El enlace [Retour au formulaire de saisie] permite al usuario volver a ver el formulario tal como lo validó.
![]() |
Por último, el botón [Effacer le formulaire] restablece el formulario a su estado inicial, c.a.d, tal como lo recibió el usuario en la solicitud inicial.
4.7. Resumen de la arquitectura MVC de la aplicación
La aplicación tiene la siguiente arquitectura MVC:
![]() |
Acabamos de describir las dos clases impots-data.php y impots-calcul.php. A continuación, describiremos los demás elementos de la arquitectura.
4.8. El controlador de la aplicación
El controlador main.php de la aplicación es el que se describió en la primera parte de este capítulo. Se trata de un controlador genérico independiente de la aplicación.
<?php
// controlador genérico
// lectura de configuración
include 'config.php';
// inclusión de bibliotecas
for($i=0;$i<count($dConfig['includes']);$i++){
include($dConfig['includes'][$i]);
}//para
// se inicia o reanuda la sesión
session_start();
$dSession=$_SESSION["session"];
if($dSession) $dSession=unserialize($dSession);
// se recupera la acción a realizar
$sAction=$_GET['action'] ? strtolower($_GET['action']) : 'init';
$sAction=strtolower($_SERVER['REQUEST_METHOD']).":$sAction";
// ¿Es normal la secuencia de acciones?
if( ! enchainementOK($dConfig,$dSession,$sAction)){
// secuencia anómala
$sAction='enchainementinvalide';
}//si
// procesamiento de la acción
$scriptAction=$dConfig['actions'][$sAction] ?
$dConfig['actions'][$sAction]['url'] :
$dConfig['actions']['actionInvalide']['url'];
include $scriptAction;
// envío de la respuesta (vista) al cliente
$sEtat=$dSession['etat']['principal'];
$scriptVue=$dConfig['etats'][$sEtat]['vue'];
include $scriptVue;
// fin del script: no se debería llegar hasta aquí a menos que haya un error
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: diccionario de configuración
// $dSession: diccionario que contiene la información de la sesión
// $dReponse: el diccionario de argumentos de la página de respuesta
//: registro de la sesión
if(isset($dSession)){
//: se guardan los parámetros de la solicitud en la sesión
$dSession['requete']=strtolower($_SERVER['REQUEST_METHOD'])=='get' ? $_GET :
strtolower($_SERVER['REQUEST_METHOD'])=='post' ? $_POST : array();
$_SESSION['session']=serialize($dSession);
session_write_close();
}else{
// sin sesión
session_destroy();
}
// se muestra la respuesta
include $dConfig['vuesReponse'][$dReponse['vuereponse']]['url'];
// fin del script
exit(0);
}//fin de sesión
//--------------------------------------------------------------------
function enchainementOK(&$dConfig,&$dSession,$sAction){
// verifica si la acción actual está autorizada en relación con el estado anterior
$etat=$dSession['etat']['principal'];
if(! isset($etat)) $etat='sansetat';
// verificación de la acción
$actionsautorisees=$dConfig['etats'][$etat]['actionsautorisees'];
$autorise= ! isset($actionsautorisees) || in_array($sAction,$actionsautorisees);
return $autorise;
}
//--------------------------------------------------------------------
function dump($dInfos){
// muestra un diccionario de información
while(list($clé,$valeur)=each($dInfos)){
echo "[$clé,$valeur]<br>\n";
}//mientras
}//seguimiento
//--------------------------------------------------------------------
function trace($msg){
echo $msg."<br>\n";
}//seguimiento
?>
4.9. Las acciones de la aplicación web
Hay cuatro acciones:
- get:init: es la acción que se activa durante la solicitud inicial sin parámetros al controlador. Genera la vista «formulario» vacía.
- post:effacerformulaire: acción activada por el botón [Effacer le formulaire]. Genera la vista [v-formulaire] vacía.
- post:calcularimpuesto: acción activada por el botón [Calculer l'impôt]. Genera la vista [v-formulaire] con el monto del impuesto a pagar o la vista [v-erreurs].
- get:retorno_formulario: acción activada por el enlace [Retour au formulaire de saisie]. Genera la vista [v-formulaire] prellenada con datos erróneos.
Estas acciones se configuran de la siguiente manera en el archivo de configuración:
<?php
…
// configuración de las acciones de la aplicación
$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 acción se le asocia el script encargado de procesarla. Cada acción llevará a la aplicación web a un estado definido por el elemento $dSession['etat']['principal']. Este estado está destinado a guardarse en la sesión. Además, la acción registra en el diccionario $dReponse la información necesaria para mostrar la vista relacionada con el nuevo estado en el que se encontrará la aplicación.
4.10. Los estados de la aplicación web
Hay dos:
- [e-formulaire]: estado en el que se presentan las diferentes variantes de la vista [v-formulaire].
- [e-erreurs]: estado en el que se presenta la vista [v-erreurs].
Las acciones permitidas en estos estados son las siguientes:
<?php
…
// configuración de los estados de la aplicación
$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'));
En un estado, las acciones autorizadas corresponden a los URL a los que apuntan los enlaces o botones [submit] de la vista asociada al estado. Además, la acción «get:init» está autorizada en todo momento. Esto le permite al usuario recuperar el URL main.php de la lista de URL de su navegador y volver a reproducirlo sin importar el estado de la aplicación. Es una especie de reinicio «manual». El estado «sin estado» solo existe al iniciar la aplicación.
A cada estado de la aplicación se le asocia un script encargado de generar la vista correspondiente a ese estado:
- estado [e-formulaire]: script e-formulaire.php
- Estado [e-erreurs]: script e-erreurs.php
El estado [e-formulaire] mostrará la vista [v-formulaire] con variantes. De hecho, la vista [v-formulaire] puede aparecer vacía, prellenada o con el monto del impuesto. La acción que llevará a la aplicación al estado [e-formulaire] especifica en la variable $dSession['etat']['principal'] el estado principal de la aplicación. El controlador solo utiliza esta información. En nuestra aplicación, la acción que lleva al estado [e-formulaire] agregará en $dSession['etat']['secondaire'] información complementaria que le permite al generador de la respuesta saber sidebe generar un formulario en blanco, prellenado, con o sin el monto del impuesto. Se podría haber procedido de otra manera, considerando que había tres estados diferentes y, por lo tanto, tres generadores de vista que escribir.
4.11. El archivo de configuración de la aplicación web config.php
<?php
// configuración de 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 de la aplicación
$dConfig['webapp']=array('titre'=>"Calculez votre impôt");
// Configuración de las vistas de la aplicación
$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';
// configuración de las acciones de la aplicación
$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');
// configuración de los informes de la aplicación
$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'));
// configuración del modelo de la aplicación
$dConfig["DSN"]=array(
"sgbd"=>"mysql",
"user"=>"seldbimpots",
"mdp"=>"mdpseldbimpots",
"host"=>"localhost",
"database"=>"dbimpots"
);
?>
4.12. Las acciones de la aplicación web
4.12.1. Funcionamiento general de los scripts de acción
- El controlador invoca un script de acción según el parámetro «action» que haya recibido del cliente.
- Tras su ejecución, el script de acción debe indicar al controlador el estado en el que debe colocarse la aplicación. Este estado debe indicarse en $dSession['etat']['principal'].
- Un script de acción puede querer almacenar información en la sesión. Lo hace colocándola en el diccionario $dSession, el cual el controlador guarda automáticamente en la sesión al final del ciclo de solicitud-respuesta.
- Un script de acción puede tener información que pasar a las vistas. Este aspecto es independiente del controlador. Se trata de la interfaz entre las acciones y las vistas, una interfaz propia de cada aplicación. En el ejemplo que estamos analizando, las acciones proporcionarán información a los generadores de vistas a través de un diccionario llamado $dReponse.
4.12.2. La acción get:init
Esta es la acción que genera el formulario vacío. El archivo de configuración muestra que será procesada por el script a-init.php:
El código del script a-init.php es el siguiente:
<?php
// se muestra el formulario de entrada
$dSession['etat']=array('principal'=>'e-formulaire', 'secondaire'=>'init');
?>
Este script simplemente establece en $dSession['etat']['principal'] el estado en el que debe encontrarse la aplicación, el estado [e-formulaire], y proporciona en $dSession['etat']['secondaire'] una especificación sobre dicho estado. El archivo de configuración nos muestra que el controlador ejecutará el script e-formulaire.php para generar la respuesta al cliente.
<?php
…
$dConfig['etats']['e-formulaire']=array(
'actionsautorisees'=>array('post:calculerimpot','get:init','post:effacerformulaire'),
'vue'=>'e-formulaire.php');
El script e-formulaire.php generará la vista [v-formulaire] en sus variantes [init] y c.a.d. El formulario estará vacío.
4.12.3. La acción post:calcularimpuesto
Esta es la acción que permite calcular el impuesto a partir de los datos ingresados en el formulario. El archivo de configuración indica que el script a-calculimpot.php es el que procesará esta acción:
El código del script a-calculimpot.php es el siguiente:
<?php
// solicitud de cálculo de impuestos
// primero se verifica la validez de los 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é";
}
// si hay errores, se detiene el proceso
if(count($erreurs)!=0){
// preparación de la página de errores
$dReponse['erreurs']=&$erreurs;
$dSession['etat']=array('principal'=>'e-erreurs','secondaire'=>'saisie');
return;
}//si
// los datos ingresados son correctos
// se recuperan los datos necesarios para calcular el impuesto
if(! $dSession['limites']){
// los datos no se encuentran en la sesión
// se recuperan de la fuente de datos
list($erreurs,$limites,$coeffr,$coeffn)=getData($dConfig['DSN']);
// si hay errores, se muestra la página de errores
if(count($erreurs)!=0){
// Preparación de la página de errores
$dReponse['erreurs']=&$erreurs;
$dSession['etat']=array('principal'=>'e-erreurs','secondaire'=>'database');
return;
}//si
// no hay errores: los datos se guardan en la sesión
$dSession['limites']=&$limites;
$dSession['coeffr']=&$coeffr;
$dSession['coeffn']=&$coeffn;
}//si
// aquí tenemos los datos necesarios para calcular el impuesto
// se calcula el impuesto
$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);
// preparación de la página de respuesta
$dSession['etat']=array('principal'=>'e-formulaire','secondaire'=>'calculimpot');
$dReponse['impot']=$dPerso['impot'];
return;
//-----------------------------------------------------------------------
function getData($dDSN){
// conexión a la fuente de datos definida por el diccionario $dDSN
$oImpots=new impots_data($dDSN);
if(count($oImpots->aErreurs)!=0) return array($oImpots->aErreurs);
// recuperación de los datos de límites, coeffr, coeffn
list($limites,$coeffr,$coeffn)=$oImpots->getData();
// se desconecta
$oImpots->disconnect();
// se devuelve el resultado
if(count($oImpots->aErreurs)!=0) return array($oImpots->aErreurs);
else return array(array(),$limites,$coeffr,$coeffn);
}//getData
El script hace lo que debe hacer: calcular el impuesto. Dejamos al lector la tarea de descifrar el código del procesamiento. Nos interesan los estados que pueden surgir como resultado de esta acción:
- los datos ingresados son incorrectos o el acceso a los datos falla: la aplicación pasa al estado [e-erreurs]. El archivo de configuración muestra que será el script e-erreurs.php el encargado de generar la vista de respuesta:
<?php
…
$dConfig['etats']['e-erreurs']=array(
'actionsautorisees'=>array('get:retourformulaire','get:init'),
'vue'=>'e-erreurs.php');
- En todos los demás casos, la aplicación pasa al estado [e-formulaire] con la variante de cálculo de impuestos indicada en $dSession['etat']['secondaire']. El archivo de configuración muestra que es el script e-formulaire.php el que generará la vista de respuesta. Utilizará el valor de $dSession['etat']['secondaire'] para generar un formulario prellenado con los valores ingresados por el usuario y, además, el monto del impuesto.
4.12.4. La acción post:borrarformulario
Está asociada, mediante configuración, al script a-init.php ya descrito.
4.12.5. La acción get:retornoFormulario
Permite regresar al estado [e-formulaire] desde el estado [e-erreurs]. El script a-retourformulaire.php es el que procesa esta acción:
El script a-retourformulaire.php es el siguiente:
<?php
// se muestra el formulario de entrada
$dSession['etat']=array('principal'=>'e-formulaire','secondaire'=>'retourformulaire');
?>
Simplemente se solicita que la aplicación se coloque en el estado [e-formulaire] en su variante [retourformulaire]. El archivo de configuración nos muestra que el controlador ejecutará el script e-formulaire.php para generar la respuesta al cliente.
<?php
…
$dConfig['etats']['e-formulaire']=array(
'actionsautorisees'=>array('post:calculerimpot','get:init','post:effacerformulaire'),
'vue'=>'e-formulaire.php');
El script e-formulaire.php generará la vista [v-formulaire] en sus variantes [retourformulaire] y c.a.d. el formulario prellenado con los valores ingresados por el usuario, pero sin el monto del impuesto.
4.13. La secuencia de acciones no es válida
Las acciones válidas a partir de un estado determinado de la aplicación se definen mediante la configuración:
<?php
…
// configuración de los estados de la aplicación
$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'));
Ya hemos explicado esta configuración. Si se detecta una secuencia de acciones no válida, se ejecuta el script a-enchainementinvalide.php:
El código de este script es el siguiente:
<?php
// secuencia de acciones no válida
$dReponse['erreurs']=array("Enchaînement d'actions invalide");
$dSession['etat']=array('principal'=>'e-erreurs','secondaire'=>'enchainementinvalide');
?>
Consiste en colocar la aplicación en el estado [e-erreurs]. En $dSession['etat']['secondaire'] proporcionamos información que será utilizada por el generador de la página de errores. Como ya hemos visto, este generador es e-erreurs.php:
<?php
…
$dConfig['etats']['e-erreurs']=array(
'actionsautorisees'=>array('get:retourformulaire','get:init'),
'vue'=>'e-erreurs.php');
Veremos el código de este generador más adelante. La vista que se envía al cliente es la siguiente:

4.14. Las vistas de la aplicación
4.14.1. Visualización de la vista final
Veamos cómo el controlador envía la respuesta al cliente, una vez ejecutada la acción solicitada por este:
<?php
…
....
// se inicia o se reanuda la sesión
session_start();
$dSession=$_SESSION["session"];
if($dSession) $dSession=unserialize($dSession);
// se recupera la acción a realizar
$sAction=$_GET['action'] ? strtolower($_GET['action']) : 'init';
$sAction=strtolower($_SERVER['REQUEST_METHOD']).":$sAction";
// ¿Es normal la secuencia de acciones?
if( ! enchainementOK($dConfig,$dSession,$sAction)){
// secuencia anómala
$sAction='enchainementinvalide';
}//si
// procesamiento de la acción
$scriptAction=$dConfig['actions'][$sAction] ?
$dConfig['actions'][$sAction]['url'] :
$dConfig['actions']['actionInvalide']['url'];
include $scriptAction;
// envío de la respuesta (vista) al cliente
$sEtat=$dSession['etat']['principal'];
$scriptVue=$dConfig['etats'][$sEtat]['vue'];
include $scriptVue;
.....
// ---------------------------------------------------------------
function finSession(&$dConfig,&$dReponse,&$dSession){
// $dConfig: diccionario de configuración
// $dSession: diccionario que contiene la información de la sesión
// $dReponse: el diccionario de argumentos de la página de respuesta
//: registro de la sesión
...
//: envío de la respuesta al cliente
include $dConfig['vuesReponse'][$dReponse['vuereponse']]['url'];
// fin del script
exit(0);
}//fin de sesión
Al regresar de un script de acción, el controlador recupera de $dSession['etat']['principal'] el estado en el que debe colocar la aplicación. Este estado fue establecido por la acción que acaba de ejecutarse. A continuación, el controlador ejecuta el generador de vistas asociado a ese estado. Encuentra el nombre de este en el archivo de configuración. La función del generador de vistas es la siguiente:
- establece en $dReponse['vuereponse'] el nombre de la plantilla de respuesta que se debe utilizar. Esta información se pasará al controlador. Una plantilla es una composición de vistas elementales que, al combinarse, forman la vista final.
- prepara la información dinámica que se mostrará en la vista final. Este punto es independiente del controlador. Se trata de la interfaz entre el generador de vistas y la vista final. Es específica de cada aplicación.
- Debe terminar obligatoriamente con la llamada a la función finSession del controlador. Esta función va a
- guardará la sesión
- enviará la respuesta
El código de la función finSession es el siguiente:
<?php
…
// ---------------------------------------------------------------
function finSession(&$dConfig,&$dReponse,&$dSession){
// $dConfig: diccionario de configuración
// $dSession: diccionario que contiene la información de la sesión
// $dReponse: el diccionario de argumentos de la página de respuesta
//: registro de la sesión
...
//: envío de la respuesta al cliente
include $dConfig['vuesReponse'][$dReponse['vuereponse']]['url'];
// fin del script
exit(0);
}//fin de sesión
La vista que se envía al usuario está definida por la entidad $dReponse['vuereponse'], la cual define la plantilla que se utilizará para la respuesta final.
4.14.2. Plantilla de la respuesta
La aplicación generará sus diferentes respuestas según el siguiente modelo único:
![]() |
Este modelo está asociado a la clave «modelo1» del diccionario $dConfig['vuesreponse']:
El script m-reponse.php se encarga de generar esta plantilla:
<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 tiene tres elementos dinámicos ubicados en un diccionario $dReponse y asociados a las siguientes claves:
- urlstyle: URL de la hoja de estilo de la plantilla
- vista1: nombre del script encargado de generar la vista vista1
- vista2: nombre del script encargado de generar la vista vista2
Un generador de vistas que desee utilizar el modelo modelo1 deberá definir estos tres elementos dinámicos. Ahora definimos las vistas elementales que pueden sustituir a los elementos [vue1] y [vue2] del modelo.
4.14.3. La vista elemental v-bandeau.php
El script v-bandeau.php genera una vista que se colocará en el á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>
El generador de vistas deberá definir dos elementos dinámicos ubicados en un diccionario $dReponse y asociados a las siguientes claves:
- título: título que se mostrará
- resultado: monto del impuesto a pagar
4.14.4. La vista elemental v-formulaire.php
La parte [vue2] corresponde ya sea a la vista [v-formulaire] o a la vista [v-erreurs]. La vista [v-formulaire] es generada por el 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>
Las partes dinámicas de esta vista, que deberá definir el generador de vistas, están asociadas a las siguientes claves del diccionario $dReponse:
- optoui: estado del botón de opción con el nombre optoui
- optnon: estado del botón de opción llamado optnon
- hijos: número de hijos que se deben colocar en el campo txtenfants
- salaire: salario anual que se debe colocar en el campo txtsalaire
4.14.5. La vista elemental v-erreurs.php
La vista [v-erreurs] es generada por el 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>
Las partes dinámicas de esta vista, que debe definir el generador de vistas, están asociadas a las siguientes claves del diccionario $dReponse:
- errores: tabla de mensajes de error
- info: mensaje informativo
- enlace: texto de un enlace
- href: URL de destino del enlace anterior
4.14.6. La hoja de estilo
Todas las vistas están «diseñadas» mediante una hoja de estilo. Para modificar el aspecto visual de la aplicación, se debe modificar su hoja de estilo. La siguiente hoja 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. Los generadores de vistas
4.15.1. Función de un generador de vistas
Recordemos la secuencia de código del controlador que ejecuta un generador de vistas:
<?php
…
// procesamiento de la acción
$scriptAction=$dConfig['actions'][$sAction] ?
$dConfig['actions'][$sAction]['url'] :
$dConfig['actions']['actionInvalide']['url'];
include $scriptAction;
// envío de la respuesta (vista) al cliente
$sEtat=$dSession['etat']['principal'];
$scriptVue=$dConfig['etats'][$sEtat]['vue'];
include $scriptVue;
Un generador de vista está vinculado al estado en el que se colocará la aplicación. La relación entre el estado y el generador de vista se establece mediante la configuración:
<?php
…
// configuración de los estados de la aplicación
$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'));
Ya hemos explicado cuál es la función de un generador de vista. Recordémosla aquí. Un generador de vista:
- establece en $dReponse['vuereponse'] el nombre de la plantilla de respuesta que se utilizará. Esta información se pasará al controlador. Una plantilla es una composición de vistas elementales que, al combinarse, forman la vista final.
- prepara la información dinámica que se mostrará en la vista final. Este punto es independiente del controlador. Se trata de la interfaz entre el generador de vistas y la vista final. Es específica de cada aplicación.
- Debe terminar obligatoriamente con la llamada a la función finSession del controlador. Esta función va a
- guardará la sesión
- enviará la respuesta
4.15.2. El generador de vista asociado al informe [e-formulaire]
El script encargado de generar la vista asociada al estado [e-formulaire] se llama e-formulaire.php:
<?php
…
$dConfig['etats']['e-formulaire']=array(
'actionsautorisees'=>array('post:calculerimpot','get:init','post:effacerformulaire'),
'vue'=>'e-formulaire.php');
Su código es el siguiente:
<?php
// se prepara la respuesta del formulario
$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'];
// configuración según el tipo de formulario que se va a generar
$type=$dSession['etat']['secondaire'];
if($type=='init'){
// formulario en blanco
$dReponse['optnon']='checked';
}//si
if($type=='calculimpot'){
// debemos volver a mostrar los parámetros de entrada almacenados en la 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';
}//si
if($type=='retourformulaire'){
// debemos volver a mostrar los parámetros de entrada almacenados en la sesión
$dReponse['optoui']=$dSession['requete']['optmarie']=='oui' ? 'checked' : '';
$dReponse['optnon']=$dReponse['optoui']=='' ? 'checked' : '';
$dReponse['enfants']=$dSession['requete']['txtenfants'];
$dReponse['salaire']=$dSession['requete']['txtsalaire'];
}//si
// se envía la respuesta
finSession($dConfig,$dReponse,$dSession);
?>
Cabe destacar que el generador de vistas cumple con los requisitos que se le exigen:
- establecer en $dReponse['vuereponse'] la plantilla de respuesta que se utilizará
- pasar información a este modelo. En este caso, la información se pasa a través del diccionario $dReponse.
- terminar con la llamada a la función finSession del controlador
Aquí, el modelo utilizado es «modelo1». Por lo tanto, el generador define los dos datos que necesita este modelo: $dReponse['vue1'] y $dReponse['vue2'].
En el caso particular de nuestra aplicación, la vista asociada al estado [e-formulaire] depende de una información almacenada en la variable $dSession['etat']['secondaire']. Se trata de una decisión de desarrollo. Otra aplicación podría optar por transmitir información complementaria de otra manera. Por otra parte, aquí toda la información necesaria para mostrar la vista final se coloca en el diccionario $dReponse. Una vez más, esta es una decisión que le corresponde al desarrollador. El estado [e-formulaire] puede producirse tras cuatro acciones diferentes: init, calcularimpuesto, regresaralformulario, borrarformulario. La vista que se debe mostrar no es exactamente la misma en todos los casos. Por ello, se han distinguido aquí tres casos en $dSession['etat']['secondaire']:
- init: el formulario se muestra vacío
- calculimpot: el formulario se muestra con el monto del impuesto y los datos que dieron lugar a su cálculo
- retorno del formulario: el formulario se muestra con los datos ingresados inicialmente
En el ejemplo anterior, el script e-formulaire.php utiliza esta información para presentar la respuesta según estas tres variantes.
4.15.3. La vista asociada al informe [e-erreurs]
El script encargado de generar la vista asociada al informe [e-erreurs] se llama e-erreurs.php y es el siguiente:
<?php
// se prepara la respuesta de error
$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';
// información adicional
$type=$dSession['etat']['secondaire'];
if($type=='database'){
$dReponse['info']="Veuillez avertir l'administrateur de l'application";
}
// se envía la respuesta
finSession($dConfig,$dReponse,$dSession);
?>
4.15.4. Visualización de la vista final
Los dos scripts que generan las dos vistas finales terminan ambos con la llamada a la función finSession del controlador:
<?php
…
function finSession(&$dConfig,&$dReponse,&$dSession){
// $dConfig: diccionario de configuración
// $dSession: diccionario que contiene la información de la sesión
// $dReponse: el diccionario de argumentos de la página de respuesta
....
//: se presenta la respuesta
include $dConfig['vuesReponse'][$dReponse['vuereponse']]['url'];
//: fin del script
exit(0);
}//fin de sesión
La vista que se envía al usuario está definida por la entidad $dReponse['vuereponse'], la cual define la plantilla que se utilizará para la respuesta final. Para los informes [e-formulaire] y [e-erreurs], esta plantilla se ha definido como «modelo1»:
Esta plantilla corresponde, según la configuración, al script m-reponse.php:
4.16. Modificar la plantilla de respuesta
Suponemos aquí que se decide cambiar el aspecto visual de la respuesta que se le da al cliente y nos interesa comprender las repercusiones que esto genera a nivel del código.
4.16.1. La nueva plantilla
La estructura de la respuesta será ahora la siguiente:
![]() |
Esta plantilla se llamará modele2 y el script encargado de generarla se llamará m-reponse2.php:
El script correspondiente a este modelo es el siguiente:
<html>
<head>
<title>Application impots</title>
<link type="text/css" href="<?php echo $dReponse['urlstyle'] ?>" rel="stylesheet" />
</head>
<body>
<table class='modele2'>
<!-- inicio del banner -->
<tr>
<td colspan="2"><?php include $dReponse['vue1']; ?></td>
</tr>
<!-- fin del banner -->
<tr>
<!-- inicio del menú -->
<td><?php include $dReponse['vue2']; ?></td>
<!-- fin del menú -->
<!-- inicio de la zona 3 -->
<td><?php include $dReponse['vue3']; ?></td>
<!-- fin de la zona 3 -->
</tr>
</table>
</body>
</html>
Los elementos dinámicos de la plantilla son los siguientes:
- $dReponse['urlstyle']: la hoja de estilo que se debe utilizar
- $dReponse['vue1']: el script que se debe utilizar para generar [vue1]
- $dReponse['vue2']: el script que se debe usar para generar [vue2]
- $dReponse['vue3']: el script que se debe utilizar para generar [vue3]
Estos elementos deberán ser definidos por los generadores de vistas.
4.16.2. Las diferentes páginas de respuesta
La aplicación presentará ahora las siguientes respuestas al usuario. En la llamada inicial, la página de respuesta será la siguiente:
![]() |
Si el usuario proporciona datos válidos, se calcula el impuesto:
![]() |
Si comete errores al ingresar los datos, se muestra la página de errores:
![]() |
Si utiliza el enlace [Retour au formulaire de saisie], vuelve a ver el formulario tal como lo validó:
![]() |
Si, como se muestra arriba, utiliza el enlace [Réinitialiser le formulaire], se le muestra un formulario en blanco:
![]() |
Cabe señalar que la aplicación utiliza las mismas acciones que antes. Solo ha cambiado el aspecto de las respuestas.
4.16.3. Las vistas elementales
La vista elemental [vue1] se asociará, al igual que en el ejemplo anterior, al 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 tiene dos elementos dinámicos:
- $dReponse['titre']: título a mostrar
- $dReponse['resultat']: monto del impuesto a pagar
La vista elemental [vue2] se asociará al siguiente 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'].
'">'.$dRespuestaQZXW2HTMLBWydsaWVucyddZQXQZXW2HTMLBWyRpXQZQXQZXW2HTMLBWyd0ZXh0ZSddZQX."</a></div></td></tr>\n";
}//$i
?>
</table>
Esta vista cuenta con los siguientes elementos dinámicos:
- $dReponse['liens']: tabla de enlaces que se mostrarán en [vue2]. Cada elemento de la tabla es un diccionario con dos claves:
- 'url': URL de destino del enlace
- 'texto': texto del enlace
La vista elemental [vue3] se asociará al script v-formulaire2.php si se desea mostrar el formulario de entrada, o al script v-erreurs2.php si se desea mostrar la página de errores. El código del script v-formulaire2.php es el siguiente:
<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>
Las partes dinámicas de esta vista, que deberá definir el generador de vistas, están asociadas a las siguientes claves del diccionario $dReponse:
- optoui: estado del botón de opción llamado optoui
- optnon: estado del botón de opción llamado optnon
- hijos: número de hijos que se deben colocar en el campo txtenfants
- salaire: salario anual que se debe colocar en el campo txtsalaire
El script que genera la página de errores se llama v-erreurs2.php. Su código es el siguiente:
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>
Las partes dinámicas de esta vista, que debe definir el generador de vistas, están asociadas a las siguientes claves del diccionario $dReponse:
- errores: tabla de mensajes de error
- info: mensaje informativo
4.16.4. La hoja de estilo
No ha cambiado. Sigue siendo style1.css.
4.16.5. El nuevo archivo de configuración
Para incorporar estas nuevas vistas, debemos modificar algunas líneas del archivo de configuración.
<?php
// configuración de PHP
ini_set("register_globals","off");
ini_set("display_errors","off");
ini_set("expose_php","off");
// lista de módulos que se deben incluir
$dConfig['includes']=array('c-impots-data.php','c-impots-calcul.php');
// controlador de la aplicación
$dConfig['webapp']=array('titre'=>"Calculez votre impôt");
// configuración de las vistas de la aplicación
$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';
// configuración de las acciones de la aplicación
$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');
// configuración de los informes de la aplicación
$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'));
// configuración del modelo de la aplicación
$dConfig["DSN"]=array(
"sgbd"=>"mysql",
"user"=>"seldbimpots",
"mdp"=>"mdpseldbimpots",
"host"=>"localhost",
"database"=>"dbimpots"
);
?>
La modificación principal consiste en cambiar los generadores de vista asociados a los informes [e-formulaire] y [e-erreurs]. Una vez hecho esto, los nuevos generadores de vista se encargan de generar las nuevas páginas de respuesta.
4.16.6. El generador de vistas asociado al informe [e-formulaire]
En el archivo de configuración, el estado [e-formulaire] ahora está asociado al generador de vistas e-formulaire2.php. El código de este script es el siguiente:
<?php
// se prepara la respuesta del formulario
$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')
);
// configuración según el tipo de formulario que se va a generar
$type=$dSession['etat']['secondaire'];
if($type=='init'){
// formulario en blanco
$dReponse['optnon']='checked';
}//si
if($type=='calculimpot'){
// debemos volver a mostrar los parámetros de entrada almacenados en la 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';
}//si
if($type=='retourformulaire'){
// debemos volver a mostrar los parámetros de entrada almacenados en la sesión
$dReponse['optoui']=$dSession['requete']['optmarie']=='oui' ? 'checked' : '';
$dReponse['optnon']=$dReponse['optoui']=='' ? 'checked' : '';
$dReponse['enfants']=$dSession['requete']['txtenfants'];
$dReponse['salaire']=$dSession['requete']['txtsalaire'];
}//si
// se envía la respuesta
finSession($dConfig,$dReponse,$dSession);
?>
Los cambios principales son los siguientes:
- el generador de vistas indica que desea utilizar el modelo de respuesta modele2
- por esta razón, completa los elementos dinámicos $dReponse['vue1'], $dReponse['vue2'], $dReponse['vue3'], los tres necesarios para la plantilla de respuesta «modele2».
- El generador también completa el elemento dinámico $dReponse['liens'], que establece los enlaces que se mostrarán en el área [vue2] de la respuesta.
4.16.7. El generador de vista asociado al informe [e-erreurs]
En el archivo de configuración, el informe [e-erreurs] ahora está asociado al generador de vista e-erreurs2.php. El código de este script es el siguiente:
<?php
// se prepara la respuesta de error
$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')
);
// información adicional
$type=$dSession['etat']['secondaire'];
if($type=='database'){
$dReponse['info']="Veuillez avertir l'administrateur de l'application";
}
// se envía la respuesta
finSession($dConfig,$dReponse,$dSession);
?>
Los cambios realizados son idénticos a los realizados en el generador de vistas e-formulaire2.php.
4.17. Conclusión
Hemos podido demostrar, con un ejemplo, las ventajas de nuestro controlador genérico. No tuvimos que escribirlo. Nos limitamos a escribir los scripts de las acciones, los generadores de vista y las vistas de la aplicación. Además, hemos demostrado las ventajas de separar las acciones de las vistas. De esta manera, pudimos cambiar el aspecto de las respuestas sin modificar ni una sola línea de código de los scripts de acción. Solo se modificaron los scripts involucrados en la generación de las vistas. Para que esto sea posible, el script de acción no debe hacer ninguna suposición sobre la vista que mostrará la información que ha calculado. Debe limitarse a entregar esa información al controlador, quien la transmite al generador de vistas para que este le dé formato. Esta es una regla absoluta: una acción debe estar completamente desconectada de las vistas.
En este capítulo nos hemos acercado a la filosofía de Struts, bien conocida por los desarrolladores de Java. Un proyecto de código abierto llamado php.mvc permite desarrollar aplicaciones web en PHP siguiendo la filosofía de Struts. Para más información, visita el sitio http://www.phpmvc.net/.













