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. |