Version 1.0.0 - 2006/01/31

8.5 Traitement des données

Les langages

La plus part des SGBD, sur tous ceux utilisés par Noas PHP, ce sont forcés de suivre la norme SQL92. Certains sont même allez jusqu’à implémenter des spécifications de SQL99. Malgré tous ces efforts les divergences entre eux existent toujours. Une bonne couche d’abstraction doit être capable de fournir également une transparence sur le langage. Il se peut que le développeur souhaite construire dynamiquement ses instructions. Noas PHP offre une abstraction pour le langage. Le framework l’utilise lui-même en interne.
L’abstraction sur les langages est assez limitée. Vous ne pouvez pas construire des commandes complexe. Vous ne pouvez pas non plus faire de sélection imbriquée. Si c’est votre souhait, passez à des instructions en langage natif dans des fichiers ou au requête comme on vous le verrez plus loin.

SQL dynamique

<php

 public function doIndexBoxEvent() {
    /* @var $oTrans NoasExchangeTransaction */   
    $oTrans = self::getApplication()->createTransaction();   
    /* @var $wordInsert NoasInsertLanguage */
    $wordInsert =
            $oTrans->getLanguage()->createInsert("bridge_dictionary");
    $oTrans->beginTransaction(NOAS_SERIALIZABLE);
 …     
    $wordInsert->initialize();
    $wordInsert->set("WORD_ID", $wordId);
    $wordInsert->set("WORD", $word);
    $oTrans->execute($wordInsert->generate());
    $oTrans->commit();
…    
    $oTrans->close();
  }

?>

Les clefs primaires et étrangères

Les clefs  sont au cœur des stratégies des systèmes d’information. Les relations physiques entre entités sont matérialisées par des instances de la classe NoasExchangeKey. Il s’agit d’une classe assez basique qui travail à bas niveau. Pour manipuler ses objets, il vous faut connaître le mapping d’où l’intérêt d’utiliser des classes dérivées afin de masquer les noms de champs (pour une meilleur encapsulation). Les clefs sont typiquement utilisées pour retrouver des objets ou définir des références et  des associations.
Même si vous bénéficiez d’une clef personnalisée, vous ne pouvez pas vous permettre de les caster systématiquement. Effectivement, lorsque vous n’êtes pas à l’origine de leur création, vous ne pouvez pas prés supposer de la classe utiliser.  Limitez donc l’utilisation des clefs personnalisées à la sélection et à l’association des objets métiers.

Définition de clef

<?php
Noas::import("noas.exchange.NoasExchangeProxy");
Noas::import("bridge.businessobject.BridgeBoxContent");

class BridgeBoxContentExchangeKey extends NoasExchangeKey {
  public function __construct($id){
    parent::__construct("BridgeBoxContent");
     $this->setExchangeValue("BOX_ID", $id);
  }
  public function getBoxId(){
     return $key->getExchangeValue("BOX_ID");
  }
  public function setBoxId($id){
    $this->setExchangeValue("BOX_ID", $id);
  }
}

?>

Les séquences numériques

La majorité des clefs primaires ne sont pas naturelle,  parce qu’elles nécessitent généralement plusieurs champs et qu’elles sont sources d’ambiguïté dans les relations. Penser à deux personnes qui portent le nom et prénom. C’est pour ces raisons, et bien d’autres encore, qu’elles sont souvent représentées par une valeur numérique. L’attribution s’effectue de manière contrôlée et l’évolution de manière chronologique, d’où le nom séquence. Ce sont les types de clef les plus répandus dans les systèmes d’information. Certain constructeur offre la possibilité d’incrémenter directement un champ lors d’une insertion. Cette fonctionnalité est quasiment inutile pour le mapping objet/relationnel. En l’utilisant vous ne disposez de la clef primaire d’une entité qu’après validation du nouvel enregistrement. Cela pose  un problème dans le monde objet car les clefs doivent être disponibles pour les agrégats et les références (impédance mismatch), sans parler des difficultés possibles pour récupérer cette nouvelle valeur. D’autre constructeur offre des générateurs externes aux tables capables de subvenir à ce besoin spécifique. La classe NoasSequence à été conçu pour modéliser ces générateurs avec la différence que tous les drivers doivent fournir ce service en utilisant des procédés natifs ou simulés. Vous pouvez ainsi disposer aisément de propriété auto-incrémentée pour vos objets métiers.

Séquence numérique

<?php

    $dc->trace("sequence stat ...");
    /* @var $oSequence NoasSequence */
    $oSequence = $oTrans->getSequence("exchange_dummy_seq");
    $oTrans->beginTransaction(NOAS_SERIALIZABLE);
    $value = $oSequence->getNextValue();
    $dc->dump_var("next sequence value", $value);
    $dc->dump_var("current sequence value"
                                                     , $oSequence->getCurrentValue());
    $dc->dump_var("next sequence value"
                                                          , $oSequence->getNextValue());
    $dc->dump_var("current sequence value"
                                                     , $oSequence->getCurrentValue());
    $oTrans->commit();

?>

Les requêtes dynamiques paramétrables

L’objectif d’un framework n’est sur tout pas de briguer le développeur sur des fonctionnalités qu’il disposait déjà. Même si Noas PHP vous donne la possibilité de mapper vos objets métier, par l’intermédiaire de procédés complexes, cette activité ne couvre pas l’intégralité des besoins au niveau base de données. Dans la mesure du raisonnable, vous pouvez toujours trouver des alternatives, pour des recherches simples par exemple. Mais si vous devez récupérer un certain nombre d’enregistrements possédant des champs calculés, vous avez tout intérêt à passer par les instructions SQL classiques. Le framework offre la classe NoasExchangeStatement pour modéliser les requêtes SQL de tout genre. La propriété principale à renseigner est la clause qui représente la requête SQL. Peut importe d’où elle provient, nous ne nous intéressons pas ici à sa définition. Vous être libre sur ce point. Si le driver que vous utilisez le permet, vous pouvez définir les propriétés de scrolling grâce à qui le résultat sera délimité. Mais la fonctionnalité la plus importante est de loin le paramétrage. Vous n’avez pour cela qu’a placer des variables dans les clauses. Pour définir un paramètre vous n’avez qu’à faire précéder son nom par le symbole « : ». Le fait d’affecter des valeurs aux paramètres s’appelle « bind ». La classe NoasExchangeStatement dispose de plusieurs méthodes pour effectuer le « bind » sur des types de données différentes (int, float, date, etc.).

Une question récurrente est de savoir ou doit-on effectuer les opérations sur les champs, au niveau base de données (requêtes SQL), ou au niveau application (programmation PHP). Si vous pouvez utiliser les commandes classiques SQL92, fait-le. Elles seront forcément plus rapides, car natives, qu’une seconde itération avec un calcule en PHP. De plus vous vous assurez de la portabilité, au niveau SQL non pris en charge par le framework, entre les différents SGBD. Par contre si vous devez effectuer des calcules complexes sur des champs,  nous vous conseillons de les effectuer en PHP. Même si le SGBD que vous utilisez dispose d’instructions suffisamment perfectionnées pour remplir ses exigences, vous avez tout intérêt à rester en PHP. Premièrement vous perdriez la notion de pseudo portabilité (portabilité par traduction) et deuxièmement le PHP est beaucoup plus complet que SQL pour ce genre de tâche. Bien sûr, vous devez analyser les situations au cas par cas. Il peut arriver qu’une requête imbriquée avec des champs calculés soit moins performante qu’une seconde itération ou l’inverse.

Les curseurs

Nous venons de parler de la construction des requêtes SQL, nous allons maintenant voir comment récupérer le résultat. Le résultat d’une requête est modélisé par les instances de classe NoasExchangeResultset. Il s’agit du résultat direct d’une exécution de requête. Pour accéder successivement aux éléments vous devez utiliser les méthodes de navigation. A chaque itération vous récupérez les données en utilisant les bonnes méthodes, c’est à dire celles qui renvoi le bon type. N’oubliez sur tout pas de libérer la ressource associée au curseur, c’est indispensable pour la majorité des systèmes.

Requête SQL

<?php
...
class UnitXmlProxyTestCase extends NoasTestCase {
...
  protected function runTest(NoasDumpContext $dc){
    $dc->trace($this->name);
    $oTrans = new NoasExchangeTransaction("db:exemple");
    $oTrans->open();
...   
    $oTrans->beginTransaction();
...   
    /* @var $oStatment NoasExchangeStatement */
    $oStatment = $oTrans->createQuery(
"select
   E_STRING, E_EMAIL, E_TIMESTAMP
from
   EXCHANGE_DUMMY
where
   EXCHANGE_DUMMY_ID in (:SV_ID_LIST)");
    $oStatment->setIn("SV_ID_LIST",
"select
  distinct(EXCHANGE_DUMMY_ID)
from
  EXCHANGE_DUMMY
where
  E_EMAIL like :SV_LIKE");
    $oStatment->setEndWith("SV_LIKE", "@noas.com");
    if($oStatment->hasScrollSupports()){
      $oStatment->setLimit(4);
      $oStatment->setOffset(2);
    }
    /* @var $oResultset NoasExchangeResultset */
    $oResultset = $oTrans->query($oStatment);
    while($oResultset->next()){
      $dc->dump_var("E_STRING", $oResultset->getString(0));   
      $dc->dump_var("E_EMAIL", $oResultset->getString(1));   
      $dc->dump_object("E_TIMESTAMP"
                                                       ,$oResultset->getTimestamp(2));   
    }        
    $oResultset->free();
...
    $oTrans->close();
...
  }
}
?>

 

© 2005 Réoka Djohou, tous droits réservés.