Skip to content

11. Oefening IMPOTS met een WEB-service en een drielaagse architectuur

We gaan de oefening IMPOTS (zie paragrafen 4.2, 4.3, 6) opnieuw bekijken en er een client/server-toepassing van maken. Het serverscript wordt opgesplitst in drie onderdelen:

  • een laag met de naam [dao] (Data Access Objects), die de communicatie met de database MySQL verzorgt
  • een laag met de naam [métier] die de belasting berekent
  • een laag met de naam [web] die de communicatie met de webclients verzorgt.

Het clientscript [1]:

  • stuurt de drie gegevens ($marié, $enfants, $salaire) die nodig zijn voor de belastingberekening door naar het serverscript
  • geeft het antwoord van de server weer op de console

Het serverscript [2] bestaat uit de serverlaag [web].

  • Bij het begin van een nieuwe clientsessie plaatst het de gegevens uit de database MySQL en [dbimpots] in tabellen. Hiervoor maakt het gebruik van de laag [dao]. De op deze manier opgebouwde tabellen worden in de sessie van de klant geplaatst, zodat ze bruikbaar zijn in latere verzoeken van de klant.
  • Bij een verzoek van de klant zal het de volgende drie gegevens doorgeven ($marié, $enfants, $salaire) door aan de laag [métier], die de belasting $impot berekent.
  • Het serverscript stuurt vervolgens de berekende belasting $impôt terug.

11.1. Het clientscript (clients_impots_05_web)

Het clientscript zal een client zijn van de webservice voor belastingberekening. Het zal (POST) parameters naar de server verzenden in de vorm:

params=$getrouwd,$kinderen,$salaris waarbij

  • $marié de tekenreeks oui of non is,
  • $enfants het aantal kinderen is,
  • $salaire het salaris van de belastingplichtige

Hij vindt de drie voorgaande parameters in een tekstbestand [data.txt] in de vorm (gehuwd, kinderen, salaris):

oui,2,200000
non,2,200000
oui,3,200000
non,3,200000
oui,5,50000
non,0,3000000

Het clientscript

  • leest het tekstbestand [data.txt] regel voor regel
  • de tekenreeks params=$marié,$enfants,$salaire naar de webservice voor belastingberekening verzenden
  • en haalt het antwoord van de service op. Dit antwoord kan twee vormen aannemen:
<erreur>message d'erreur</erreur>
<impot>montant de l'impôt</impot>
  • slaat het antwoord van de server op in een tekstbestand [resultats.txt] in een van de volgende twee vormen:
marié:enfants:salaire:erreur
marié:enfants:salaire:impôt

De code van het clientscript is als volgt:


<?php

// belastingklant
// foutbeheer
ini_set("display_errors", "off");

// ---------------------------------------------------------------------------------
// een klasse met hulpprogramma's
class Utilitaires {

  function cutNewLinechar($ligne) {
    ...
  }

}

// main -----------------------------------------------------
// definitie van constanten
$DATA = "data.txt";
$RESULTATS = "resultats.txt";
// servergegevens
$HOTE = "localhost";
$PORT = 80;
$urlServeur = "/exemples-web/impots_05_web.php";

// de parameters van belastingplichtigen (burgerlijke staat, aantal kinderen, jaarsalaris)
// zijn in het tekstbestand $DATA geplaatst, met één regel per belastingplichtige
// de resultaten (burgerlijke staat, aantal kinderen, jaarsalaris, te betalen belasting) 
// of (burgerlijke staat, aantal kinderen, jaarsalaris, foutmelding) zijn geplaatst in
// het tekstbestand $RESULTATS, met één resultaat per regel

// klasse Hulpprogramma’s
$u = new Utilitaires();

// het bestand met de gegevens van de belastingplichtigen openen
$data = fopen($DATA, "r");
if (!$data) {
  print "Impossible d'ouvrir en lecture le fichier des données [$DATA]\n";
  exit;
}

// het resultatenbestand openen
$résultats = fopen($RESULTATS, "w");
if (!$résultats) {
  print "Impossible de créer le fichier des résultats [$RESULTATS]\n";
  exit;
}

// de huidige regel van het bestand met belastingplichtigengegevens wordt verwerkt
while ($ligne = fgets($data, 100)) {
  // eventueel einde-van-regel-teken verwijderen
  $ligne = $u->cutNewLineChar($ligne);
  // de 3 velden ‘gehuwd:kinderen:salaris’ worden opgehaald, die samen $ligne vormen
  list($marié, $enfants, $salaire) = explode(",", $ligne);
  // de belasting wordt berekend
  list($erreur, $impôt) = calculerImpot($HOTE, $PORT, $urlServeur, $cookie, array($marié, $enfants, $salaire));
  // het resultaat wordt ingevuld
  $résultat = $erreur ? "$marié:$enfants:$salaire:$erreur" : "$marié:$enfants:$salaire:$impôt";
  fputs($résultats, "$résultat\n");
  // volgende gegevens
}
// de bestanden worden gesloten
fclose($data);
fclose($résultats);

// einde
print "Terminé...\n";
exit;

function calculerImpot($HOTE, $PORT, $urlServeur, &$cookie, $params) {
  // verbindt de klant met ($HOTE,$PORT,$urlServeur)
  // verzendt de cookie $cookie als deze niet leeg is. $cookie wordt doorverwezen
  // stuurt $params naar de server
  // verwerkt de enige regel die door de server wordt teruggestuurd
  
  // opent een verbinding op poort 80 van $HOTE
  $connexion = fsockopen($HOTE, $PORT);
  // fout?
  if (!$connexion)
    return array("erreur lors de la connexion au serveur ($HOTE, $PORT)");
  // de headers van het protocol HTTP moeten eindigen met een lege regel
  // POST
  fputs($connexion, "POST $urlServeur HTTP/1.1\n");
  // Host
  fputs($connexion, "Host: localhost\n");
  // Verbinding
  fputs($connexion, "Connection: close\n");
// de cookie wordt verzonden als deze niet leeg is
  if ($cookie) {
    fputs($connexion, "Cookie: $cookie\n");
  }//if
  // nu wordt de clientinstructie verzonden nadat deze is gecodeerd
  $infos = "params=" . urlencode(implode(",", $params));
  // we geven aan welk type informatie we gaan verzenden
  fputs($connexion, "Content-type: application/x-www-form-urlencoded\n");
  // de grootte (aantal tekens) van de informatie die wordt verzonden, wordt verzonden
  fputs($connexion, "Content-length: " . strlen($infos) . "\n");
  // we verzenden een lege regel
  fputs($connexion, "\n");
  // de informatie wordt verzonden
  fputs($connexion, $infos);
  // hiermee wordt het antwoord van de webserver weergegeven
  // en zorg ervoor dat je de eventuele cookie ophaalt
  while ($ligne = fgets($connexion, 1000)) {
    // cookie – alleen bij het eerste antwoord
    if (!$cookie) {
      if (preg_match("/^Set-Cookie: (.*?)\s*$/", $ligne, $champs)) {
        $cookie = $champs[1];
      }//if
    }
    // zodra er een lege regel is, is het antwoord HTTP voltooid
    if (trim($ligne) == "") {
      break;
    }
  }//while
  // lees een regel uit het resultaat
  $ligne = fgets($connexion, 1000);
  // de verbinding wordt verbroken
  fclose($connexion);
  // resultaat berekenen
  $erreur="";
  $impôt="";
  if (preg_match("/^<erreur>(.*?)<\/erreur>\s*$/", $ligne, $champs)) {
    $erreur = $champs[1];
  } else {
    if (preg_match("/^<impot>(.*?)<\/impot>\s*$/", $ligne, $champs)) {
      $impôt = $champs[1];
    }else{
      $erreur="résultat du serveur non exploitable";
    }
  }
  // terug
  return array($erreur, $impôt);
}

Opmerkingen

De code van het clientscript bevat elementen die we al eerder hebben gezien:

  • regels 9-15: de klasse [Utilitaires] is beschreven in versie 3, paragraaf 6
  • regels 17-68: het hoofdprogramma is vergelijkbaar met dat van versie 1, paragraaf 4.2. Het verschilt daar alleen van door de berekening van de belasting, regel 56.
  • regel 56: de functie voor de berekening van de belasting accepteert de volgende parameters:
    • $HOTE, $PORT, $urlServeur: hiermee kan verbinding worden gemaakt met de webservice
    • $cookie: dit is de sessiecookie. Deze parameter wordt doorverwezen. De waarde ervan wordt bepaald door de functie voor de belastingberekening. Bij de eerste aanroep heeft deze geen waarde. Daarna heeft deze wel een waarde.
    • array($marié, $enfants, $salaire): vertegenwoordigt een regel uit het bestand [data.txt]

De functie voor het berekenen van de belasting retourneert een array met twee resultaten ($erreur, $impôt), waarbij $erreur een eventuele foutmelding is en $impôt het belastingbedrag.

  • regels 70 – 134: hier zien we een klassieke HTTP-client zoals we die al vaak zijn tegengekomen. Let op de volgende punten:
  • regel 83: de parameters ($marié, $enfants, $salaire) worden via een POST naar de server verzonden
  • regels 89-91: als de client een sessie-ID heeft, stuurt hij deze naar de server
  • regel 93: aanmaken van de parameter params
  • regel 101: verzending van de parameter params
  • regels 104-115: de client leest alle door de server verzonden HTTP-headers totdat de lege regel aan het einde van de headers wordt bereikt. Hij maakt van de gelegenheid gebruik om de sessie-ID op te halen in het antwoord op zijn eerste verzoek.
  • regels 123-125: er wordt gebruikgemaakt van een eventuele regel in de vorm <erreur>message</erreur>
  • regels 126-128: we doen hetzelfde met een eventuele regel in de vorm <impot>montant</impot>
  • regel 133: het resultaat wordt weergegeven

11.2. De webservice voor belastingberekening

We richten ons hier op de drie scripts waaruit de server bestaat:

Het bijbehorende NetBeans-project is het volgende:

In [1] bestaat de server uit de volgende PHP-scripts:

  • [impots_05_entites] bevat de klassen die door de server worden gebruikt
  • [impots_05_dao] bevat de klassen en interfaces van de laag [dao]
  • [impots_05_metier] bevat de klassen en interfaces van de laag [metier]
  • [impots_05_web] bevat de klassen en interfaces van de laag [dao]

We beginnen met de presentatie van twee klassen die door de verschillende lagen van de webservice worden gebruikt.

11.2.1. De entiteiten van de webservice (impots_05_entites)

De database MySQL [dbimpots] bevat een tabel [impots] met de gegevens die nodig zijn voor de berekening van de belasting [1]:

We zullen de gegevens uit de tabellen MySQL en [impots] opslaan in een objectarray Tranche, waarbij Tranche de volgende klasse is:


<?php

// een belastingschijf
class Tranche {

  // privévelden
  private $limite;
  private $coeffR;
  private $coeffN;

  // getters en setters
  public function getLimite() {
    return $this->limite;
  }

  public function setLimite($limite) {
    $this->limite = $limite;
  }

  public function getCoeffR() {
    return $this->coeffR;
  }

  public function setCoeffR($coeffR) {
    $this->coeffR = $coeffR;
  }

  public function getCoeffN() {
    return $this->coeffN;
  }

  public function setCoeffN($coeffN) {
    $this->coeffN = $coeffN;
  }

  // constructor
  public function __construct($limite, $coeffR, $coeffN) {
    $this->setLimite($limite);
    $this->setCoeffR($coeffR);
    $this->setCoeffN($coeffN);
  }

  // toString
  public function __toString(){
    return "[$this->limite,$this->coeffR,$this->coeffN]";
  }
}

De privévelden [$limite, $coeffR, $coeffN] worden gebruikt om de kolommen [limites, coeffR, coeffN] van een rij in de tabel MySQL [impots] op te slaan.

Bovendien zal de servercode gebruikmaken van een eigen uitzondering, de klasse ImpotsException:

1
2
3
4
5
6
7
class ImpotsException extends Exception {

  public function __construct($message, $code=0) {
    parent::__construct($message, $code);
  }

}
  • regel 1: de klasse [ImpotsException] is afgeleid van de klasse [Exception], die vooraf is gedefinieerd in PHP 5
  • regel 3: de constructor van de klasse [ImpotsException] accepteert twee parameters:
    • $message: een foutmelding
    • $code: een foutcode

11.2.2. De laag [dao] (impots_05_dao)

De laag [dao] zorgt voor toegang tot de gegevens in de database:

De laag [dao] heeft de volgende interface:

1
2
3
4
5
6
// Dao-interface
interface IImpotsDao {

// geeft een array van Tranche-entiteiten terug
  function getData();
}

De interface IImpotsDao biedt alleen de functie getData aan. Deze functie plaatst de verschillende rijen van de tabel MySQL [dbimpots.impots] in een array van objecten Tranche.

De implementatieklasse is als volgt:


<?php

// Dao-laag
// afhankelijkheden
require_once "impots_05_entites.php";
// constanten
define("TABLE", "impots");

// -----------------------------------------------------------------
// abstracte implementatie
abstract class ImpotsDaoWithPdo implements IImpotsDao {

// privévelden
  private $dsn;
  private $user;
  private $passwd;
  private $tranches;

// getters en setters
  public function getDsn() {
    return $this->dsn;
  }

  public function setDsn($dsn) {
    $this->dsn = $dsn;
  }

  public function getUser() {
    return $this->user;
  }

  public function setUser($user) {
    $this->user = $user;
  }

  public function getPasswd() {
    return $this->passwd;
  }

  public function setPasswd($passwd) {
    $this->passwd = $passwd;
  }

  // constructor
  public function __construct($dsn, $user, $passwd) {
    // de parameters worden opgeslagen
    $this->setDsn($dsn);
    $this->setUser($user);
    $this->setPasswd($passwd);
    // gegevens ophalen uit SGBD
    // verbindt ($user,$pwd) met de database $dsn
    try {
      // verbinding
      $connexion = new PDO($dsn, $user, $passwd, array(PDO::ATTR_PERSISTENT => true));
      // leest de tabel $TABLE
      $requête = "select limites,coeffR,coeffN from " . TABLE;
      // voert de query $requête uit op de verbinding $connexion
      $statement = $connexion->prepare($requête);
      $statement->execute();
      // verwerking van het resultaat van de query
      while ($colonnes = $statement->fetch()) {
        $this->tranches[] = new Tranche($colonnes[0], $colonnes[1], $colonnes[2]);
      }
      // verbinding verbreken
      $connexion=NULL;
    } catch (PDOException $e) {
      // terugkeer met fout
      throw new ImpotsException($e->getMessage(), 1);
    }
  }

  public function getData(){
    return $this->tranches;
  }
}
  • regel 5: de implementatie van de interface [IImpotsDao] heeft de klassen nodig die zijn gedefinieerd in het script [impots_05_entites].
  • regel 11: definitie van een abstracte klasse. Een abstracte klasse is een klasse waarvan geen instantie kan worden gemaakt. Een abstracte klasse moet verplicht worden afgeleid om te kunnen worden geïnstantieerd. Een klasse kan als abstract worden gedeclareerd omdat er geen instantie van kan worden gemaakt (sommige methoden zijn niet gedefinieerd) of omdat men geen instantie wil maken. In dit geval willen we geen instantie maken van de klasse [ImpotsDaoWithPdo]. We zullen wel instanties maken van afgeleide klassen.
  • regel 11: de klasse [ImpotsDaoWithPdo] implementeert de interface [IImpotsDao]. Daarom moet deze de methode getData definiëren. Deze methode staat op de regels 72-74.
  • regel 14: $dsn (Data Source Name) is een tekenreeks die de SGBD en de gebruikte database op unieke wijze identificeert.
  • regel 15: $user identificeert de gebruiker die verbinding maakt met de database
  • regel 16: $passwd is het wachtwoord van de vorige gebruiker
  • regel 17: $tranches is de objectenarray Tranche waarin de tabel MySQL [dbimpots.impots] zal worden opgeslagen.
  • regels 45-70: de constructor van de klasse. Deze code is al aan bod gekomen in versie 4, paragraaf 8.2. Merk op dat het aanmaken van het object [ImpotsDaoWithPdo] kan mislukken. In dat geval wordt een uitzondering van het type [ImpotsException] gegenereerd.
  • regels 72-74: de methode [getData] van de interface [IImpotsDao].

De klasse [ImpotsDaoWithPdo] is geschikt voor elke SGBD. De constructor van de klasse, regel 45, vereist dat de Data Source Name van de database bekend is. Deze tekenreeks is afhankelijk van de gebruikte SGBD. We hebben ervoor gekozen om de gebruiker van de klasse niet te verplichten deze Data Source Name te kennen. Voor elke SGBD zal er een specifieke klasse zijn die is afgeleid van [ImpotsDaoWithPdo]. Voor de SGBD en MySQL is dat de volgende klasse:


class ImpotsDaoWithMySQL extends ImpotsDaoWithPdo {

  public function __construct($host, $port, $base, $user, $passwd) {
    parent::__construct("mysql:host=$host;dbname=$base;port=$port", $user, $passwd);
  }

}
  • in regel 3 vraagt de ontwikkelaar niet om de Data Source Name, maar alleen om de naam van de hostmachine van SGBD ($host), de luisterpoort ($port) en de naam van de database ($base).
  • In regel 4 wordt de Data Source Name van de database MySQL samengesteld en gebruikt om de constructor van de bovenliggende klasse aan te roepen.

Merk op dat het, om aan te passen aan een andere SGBD, volstaat om de juiste, van [ImpotsDaoWithPdo] afgeleide klasse te schrijven. Het gaat er telkens om de Data Source Name samen te stellen die specifiek is voor de gebruikte SGBD.

11.2.3. De laag [métier] (impots_05_metier)

De laag [metier] bevat de logica voor de belastingberekening:

De laag [métier] heeft de volgende interface:


<?php

// bedrijfsinterface
interface IImpotsMetier {
  public function calculerImpot($marié, $enfants, $salaire);
}

De interface [IImpotsMetier] biedt slechts één methode aan, namelijk de methode [calculerImpot], waarmee de belasting van een belastingplichtige kan worden berekend op basis van de volgende parameters:

  • $marié: tekenreeks ‘ja’ of ‘nee’, afhankelijk van of de belastingplichtige al dan niet gehuwd is
  • $enfants: het aantal kinderen van de belastingplichtige
  • $salaire: zijn salaris

De laag [web] levert deze parameters aan.

De implementatie van de interface [IImpotsMetier] is als volgt:


// afhankelijkheden
require_once "impots_05_dao.php";

// ------------------------------------------------------------------
// implementatieklasse
class ImpotsMetier implements IImpotsMetier {

  // DAO-laag
  private $dao;
   // objectarray [Tranche]
  private $data;

  // getter en setter
  public function getDao() {
    return $this->dao;
  }

  public function setDao($dao) {
    $this->dao = $dao;
  }

  public function setData($data){
    $this->data=$data;
  }
  
  public function __construct($dao) {
    // de gegevens ophalen die nodig zijn voor de berekening van de belasting
    $this->setDao($dao);
    $this->setData($this->dao->getData());
  }

  public function calculerImpot($marié, $enfants, $salaire) {
    // $marié: ja, nee
    // $enfants: aantal kinderen
    // $salaire: jaarsalaris
    // aantal aandelen
    $marié = strtolower($marié);
    if ($marié == "oui")
      $nbParts = $enfants / 2 + 2;
    else
      $nbParts=$enfants / 2 + 1;
    // een half aandeel extra bij ten minste 3 kinderen
    if ($enfants >= 3)
      $nbParts+=0.5;
    // belastbaar inkomen
    $revenuImposable = 0.72 * $salaire;
    // gezinsquotiënt
    $quotient = $revenuImposable / $nbParts;
    // wordt aan het einde van de tabel met drempels geplaatst om de daaropvolgende lus te beëindigen
    $N = count($this->data);
    $this->data[$N - 1]->setLimite($quotient);
    // berekening van de belasting
    $i = 0;
    while ($i < $N and $quotient > $this->data[$i]->getLimite()) {
      $i++;
    }
    // omdat $quotient aan het einde van de tabel $limites is geplaatst, de voorgaande lus
    // mag niet buiten de tabel $limites vallen
    // nu kunnen we de belasting berekenen
    return floor($revenuImposable * $this->data[$i]->getCoeffR() - $nbParts * $this->data[$i]->getCoeffN());
  }

}
  • regel 2: de laag [métier] heeft de klassen van de laag [dao] en de entiteiten (Tranche, ImpotsException) nodig.
  • regel 6: de klasse [ImpotsMetier] implementeert de interface [IimpotsMetier].
  • regels 9-11: de privévelden van de klasse:
    • $dao: verwijzing naar de laag [dao]
    • $data: array van objecten van het type [Tranche], geleverd door de laag [dao]
  • regels 26-30: de constructor van de klasse initialiseert de twee voorgaande velden. Hij ontvangt als parameter een verwijzing naar de laag [dao].
  • regels 32-61: implementatie van de methode [calculerImpot] van de interface [IimpotsMetier]. Deze methode kwam al voor in versie 1 (paragraaf 4.2).

11.2.4. De laag [web] (impots_05_web)

De laag [metier] bevat de logica voor de belastingberekening:

De laag [web] bestaat uit de webservice die reageert op webclients. Ter herinnering: deze doen een verzoek aan de webservice door de volgende parameter te verzenden: params=marié,enfants,salaire. Het gaat hier om een webservice zoals we die in de voorgaande paragrafen hebben kunnen bouwen. De code ervan is als volgt:


<?php

// bedrijfslaag
require_once "impots_05_metier.php";

// foutbeheer
ini_set("display_errors", "off");

// koptekst UTF-8
header("Content-Type: text/plain; charset=utf-8");

// ------------------------------------------------------------------------------
// de webdienst voor belastingen
// definitie van constanten
$HOTE = "localhost";
$PORT = 3306;
$BASE = "dbimpots";
$USER = "root";
$PWD = "";
// de gegevens die nodig zijn voor de belastingberekening zijn in de MySQL-tabel IMPOTS geplaatst
// die deel uitmaakt van de database $BASE. De tabel heeft de volgende structuur
// limieten decimal(10,2), coeffR decimal(6,2), coeffN decimal(10,2)
// de parameters van de belastingplichtigen (burgerlijke staat, aantal kinderen, jaarsalaris)
// worden door de klant verzonden in de vorm params=burgerlijke staat, aantal kinderen, jaarsalaris
// de resultaten (burgerlijke staat, aantal kinderen, jaarsalaris, te betalen belasting) worden teruggestuurd naar de klant
// in de vorm <belasting>belasting</belasting>
// of in de vorm <fout>fout</fout>, als de parameters ongeldig zijn

// wordt de laag [métier] in de sessie opgehaald
session_start();
if (!isset($_SESSION['metier'])) {
// instantiëring van de laag [dao] en de laag [métier]
  try {
    $_SESSION['metier'] = new ImpotsMetier(new ImpotsDaoWithMySQL($HOTE, $PORT, $BASE, $USER, $PWD));
  } catch (ImpotsException $ie) {
    print "<erreur>Erreur : " . utf8_encode($ie->getMessage() . "</erreur>");
    exit;
  }
}
$metier = $_SESSION['metier'];

// de door de klant verzonden regel wordt opgehaald
$params = utf8_encode(htmlspecialchars(strtolower(trim($_POST['params']))));
$items = explode(",", $params);
// er mogen slechts 3 parameters zijn
if (count($items) != 3) {
  print "<erreur>[$params] : nombre de paramètres invalides</erreur>\n";
  exit;
}//if
// de eerste parameter (burgerlijke staat) moet ja/nee zijn
$marié = trim($items[0]);
if ($marié != "oui" and $marié != "non") {
  print "<erreur>[$params] : 1er paramètre invalide</erreur>\n";
  exit;
}//if
// de tweede parameter (aantal kinderen) moet een geheel getal zijn
if (!preg_match("/^\s*(\d+)\s*$/", $items[1], $champs)) {
  print "<erreur>[$params] : 2ième paramètre invalide</erreur>\n";
  exit;
}//if
$enfants = $champs[1];
// de derde parameter (salaris) moet een geheel getal zijn
if (!preg_match("/^\s*(\d+)\s*$/", $items[2], $champs)) {
  print "<erreur>[$params] : 3ième paramètre invalide</erreur>\n";
  exit;
}//if
$salaire = $champs[1];
// de belasting wordt berekend
$impôt = $metier->calculerImpot($marié, $enfants, $salaire);
// het resultaat wordt teruggegeven
print "<impot>$impôt</impot>\n";
// einde
exit;
  • regel 4: de laag [web] heeft de klassen van de laag [métier] nodig
  • regels 30-40: de verwijzing naar de laag [métier] wordt in de sessie opgenomen. Als we bedenken dat deze laag [métier] een verwijzing bevat naar de laag [dao] en dat deze laatste de gegevens van de SGBD opslaat, dan wordt duidelijk:
    • dat het eerste verzoek van de klant een toegang tot de laag SGBD zal veroorzaken
    • dat de volgende verzoeken van dezelfde klant gebruik zullen maken van de gegevens die zijn opgeslagen door de laag [dao]. Er vindt dus geen toegang plaats tot SGBD.
  • regel 34: aanmaken van een laag [métier] die samenwerkt met een laag [dao], geïmplementeerd voor de SGBD MySQL
  • regels 35-37: afhandeling van een eventuele fout in de vorige bewerking. In dat geval wordt een regel <erreur>message</erreur> naar de klant verzonden.
  • regel 43: de parameter 'params' wordt opgehaald die door de klant is verzonden.
  • regels 46-49: het aantal gegevens in 'params' wordt gecontroleerd
  • regels 51-55: de geldigheid van het eerste gegevenselement wordt gecontroleerd
  • regels 56-60: idem voor het tweede item
  • regels 62-66: hetzelfde geldt voor het derde gegeven
  • regel 69: de laag [métier] berekent de belasting.
  • regel 71: het resultaat wordt naar de klant verzonden

Resultaten

We herinneren ons dat de klant [client_impots_web_05] het volgende bestand [data.txt] gebruikt:

oui,2,200000
non,2,200000
oui,3,200000
non,3,200000
oui,5,50000
non,0,3000000

Op basis van deze regels (gehuwd, kinderen, salaris) vraagt de client de belastingberekeningsserver om informatie en schrijft de resultaten weg in het tekstbestand [resultats.txt]. Na uitvoering van de client is de inhoud van dit bestand als volgt:

oui:2:200000:22504
non:2:200000:33388
oui:3:200000:16400
non:3:200000:22504
oui:5:50000:0
non:0:3000000:1354938

waarbij elke regel de volgende vorm heeft (gehuwd, kinderen, salaris, berekende belasting).