2.Introduction à la programmation web en PHP
3.2 Application Impôts : la classe ImpotsDSN
Notre application s'appuiera sur la classe PHP ImpotsDSN qui aura les attributs, constructeur et méthode suivante : // attributs
var $limites; // tableau des limites
1
2 3
4
var $coeffR; // tableau des coeffR
var $coeffN; // tableau des coeffN
var $erreurs; // tableau des erreurs
// constructeur
function ImpotsDSN($impots){...} // méthode
function calculer($personne){...}
nous avons vu dans l'exposé du problème que nous avions besoin de trois séries de données
12620.0 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.5 55790 0.35 9316.5 92970 0.4 12106 127860 0.45 16754.5 151250 0.50 23147.5 172040 0.55 30710 195000 0.60 39312 0 0.65 49062
La 1ère colonne sera placée dans l'attribut $limites de la classe ImotsDSN, la seconde dans l'attribut $coeffR, la troisième dans $coeffN. Ces trois attributs sont initialisés par le constructeur de la classe. Celui-ci va chercher les données dans une source de données ODBC. Diverses erreurs peuvent se produire lors de la construction de l'objet. Ces erreurs sont rapportées dans l'attribut $erreurs sous la forme d'un tableau de messages d'erreurs.
le constructeur reçoit en paramètre un dictionnaire $impots avec les champs suivants :
// dsn : nom DSN de la source ODBC de données contenant les valeurs des tableaux limites, coeffR, coeffN // user : nom d'un utilisateur ayant un droit de lecture sur la source ODBC
// pwd : son mot de passe
// table : nom de la table contenant les valeurs (limites, coeffR, coeffN) // limites : nom de la colonne contenant les valeurs limites
// coeffR : nom de la colonne contenant les valeurs coeffR // coeffN : nom de la colonne contenant les valeurs coeffN
Le paramètre du constructeur apporte toutes les informations nécessaires pour aller lire les données dans la source de données ODBC
une fois l'objet ImpotsDSN construit, les utilisateur de la classe pourront appeler la méthode calculerImpots de l'objet. Celui- ci reçoit en paramètre un dictionnaire $personne :
// $personne["marié"] : oui, non
// $personne["enfants"] : nombre d'enfants // $personne["salaire"] : salaire annuel La classe complète est la suivante :
<?php
// définition d'une classe objImpots class ImpotsDSN{
// attributs : les 3 tableaux de données var $limites; // tableau des limites var $coeffR; // tableau des coeffR var $coeffN; // tableau des coeffN var $erreurs; // tableau des erreurs // constructeur
function ImpotsDSN($impots){
// $impots : dictionnaire contenant les champs suivants
// dsn : nom DSN de la source ODBC de données contenant les valeurs des tableaux limites, coeffR, coeffN
// user : nom d'un utilistaeur ayant un droit de lecture sur la source ODBC // pwd : son mot de passe
// table : nom de la table contenant les valeurs (limites, coeffR, coeffN) // limites : nom de la colonne contenant les valeurs limites
// coeffR : nom de la colonne contenant les valeurs coeffR // coeffN : nom de la colonne contenant les valeurs coeffN
// au départ pas d'erreurs $this->erreurs=array();
// vérification de l'appel
if (! isset($impots[dsn]) || ! isset($impots[user]) ||! isset($impots[pwd]) ||! isset($impots [table]) ||
! isset($impots[limites]) ||! isset($impots[coeffR]) ||! isset($impots[coeffN])){ // erreur $this->erreurs[]="Appel incorrect"; // fin return; }//if // ouverture de la base DSN $connexion=odbc_connect($impots[dsn],$impots[user],$impots[pwd]); // erreur ? if(! $connexion){ // erreur
$this->erreurs[]="Impossible d'ouvrir la base DSN [$impots[dsn]] (".odbc_error().")"; // fin
return; }//if
// émission d'une requête sur la base
$requête=odbc_prepare($connexion,"select $impots[limites],$impots[coeffR],$impots[coeffN] from $impots[table]");
if(! odbc_execute($requête)){ // erreur
$this->erreurs[]="Impossible d'expoiter la base DSN [$impots[dsn]] (".odbc_error().")"; // fin
odbc_close($connexion); return;
}//if
// exploitation des résultats de la requête $this->limites=array();
$this->coeffR=array(); $this->coeffN=array();
while(odbc_fetch_row($requête)){ // une ligne de plus
$this->limites[]=odbc_result($requête,$impots[limites]); $this->coeffR[]=odbc_result($requête,$impots[coeffR]); $this->coeffN[]=odbc_result($requête,$impots[coeffN]); }//while // fermeture base odbc_close($connexion); }//constructeur // --- function calculer($personne){
// $personne["marié"] : oui, non
// $personne["enfants"] : nombre d'enfants // $personne["salaire"] : salaire annuel // l'objet est-il dans un état correct ?
if (! is_array($this->erreurs) || count($this->erreurs)!=0) return -1; // vérification de l'appel
if (! isset($personne[marié]) || ! isset($personne[enfants]) ||! isset($personne[salaire])){ // erreur $this->erreurs[]="Appel incorrect"; // fin return -1; }//if
// les paramètres sont-ils corrects ?
$personne[marié]=strtolower($personne[marié]); if($personne[marié]!=oui && $personne[marié]!=non){ // erreur
$this->erreurs[]="Statut marital [$personne[marié]] incorrect"; }//if
if(! preg_match("/^\s*\d{1,3}\s*$/",$personne[enfants])){ // erreur
$this->erreurs[]="Nombre d'enfants [$personne[enfants]] incorrect"; }//if
if(! preg_match("/^\s*\d+\s*$/",$personne[salaire])){ // erreur
$this->erreurs[]="salaire [$personne[salaire]] incorrect"; }//if
// des erreurs ?
if(count($this->erreurs)!=0) return -1;
// nombre de parts
if($personne[marié]==oui) $nbParts=$personne[enfants]/2+2; else $nbParts=$personne[enfants]/2+1;
// une 1/2 part de plus si au moins 3 enfants if($personne[enfants]>=3) $nbParts+=0.5; // revenu imposable
$revenuImposable=0.72*$personne[salaire]; // quotient familial
$quotient=$revenuImposable/$nbParts;
// est mis à la fin du tableau limites pour arrêter la boucle qui suit $this->limites[$this->nbLimites]=$quotient;
// calcul de l'impôt $i=0;
while($quotient>$this->limites[$i]) $i++;
// du fait qu'on a placé $quotient à la fin du tableau $limites, la boucle précédente // ne peut déborder du tableau $limites
// maintenant on peut calculer l'impôt
return floor($revenuImposable*$this->coeffR[$i]-$nbParts*$this->coeffN[$i]); }//calculImpots
}//classe impôts ?>
Un programme de test pourrait être le suivant : <?php
// bibilothèques
include "ImpotsDSN.php";
// création d'un objet impots
$conf=array(dsn=>"mysql-dbimpots",user=>admimpots,pwd=>mdpimpots, table=>impots,limites=>limites,coeffR=>coeffR,coeffN=>coeffN); $objImpots=new ImpotsDSN($conf); // des erreurs ? if(count($objImpots->erreurs)!=0){ // msg
echo "Les erreurs suivantes se sont produites :\n"; $erreurs=$objImpots->erreurs; for($i=0;$i<count($erreurs);$i++){ echo "$erreurs[$i]\n"; }//for // fin exit(1); }//if // des essais calculerImpots($objImpots,oui,2,200000); calculerImpots($objImpots,non,2,200000); calculerImpots($objImpots,oui,3,200000); calculerImpots($objImpots,non,3,200000); calculerImpots($objImpots,array(),array(),array()); // fin exit(0); // --- function calculerImpots($objImpots,$marié,$enfants,$salaire){ // echo echo "impots($marié,$enfants,$salaire)\n"; // calcul de l'impôt $personne=array(marié=>$marié,enfants=>$enfants,salaire=>$salaire); $montant=$objImpots->calculer($personne); // des erreurs ? if(count($objImpots->erreurs)!=0){ // msg
echo "Les erreurs suivantes se sont produites :\n"; $erreurs=$objImpots->erreurs;
for($i=0;$i<count($erreurs);$i++){ echo "$erreurs[$i]\n";
}//for
}else echo "montant=$montant\n"; }//calculerImp
le programme de test prend soin d"inclure" le fichier contenant la classe ImpotsDSN
puis crée un objet objImpots de la classe ImpotsDSN en passant au constructeur de l'objet les informations dont il a besoin une fois cet objet créé, la méthode calculer de celui-ci va être appelée cinq fois
dos>e:\php43\php.exe test.php impots(oui,2,200000) montant=22504 impots(non,2,200000) montant=33388 impots(oui,3,200000) montant=16400 impots(non,3,200000) montant=22504 impots(Array,Array,Array)
Les erreurs suivantes se sont produites : Statut marital [array] incorrect
Nombre d'enfants [Array] incorrect salaire [Array] incorrect
Nous utiliserons désormais la classe ImpotsDSN sans en redonner la définition.