Manuel PHP
Précédent |  | Suivant

# CXXXIII. Fonctions SDO Relationnel Service d'Accès de Données

# Introduction

Avertissement
Ce module est EXPERIMENTAL. Cela signifie que le comportement de ces fonctions, leurs noms et concrètement, TOUT ce qui est documenté ici peut changer dans un futur proche, SANS PREAVIS! Soyez-en conscient, et utilisez ce module à vos risques et périls.

Afin d'utiliser le Service d'Accès de Données Relationnel pour les Objets de Service de Données, vous devrez comprendre certains concepts derrière le SDO : le graphique de données, l'objet de données, le moyen de déconnexion pour travailler, le changement du sommaire, les expressions XPath et les propriétés, et ainsi de suite. Si vous n'êtes pas familier avec ses idées, vous devriez regarder en premier à la section sur le SDO. De plus, le DAS Relationnel utilise l'extension SDO pour s'isoler des communications spécifiques aux bases de données. Afin d'utiliser le DAS Relationnel, vous devrez être capable de créer et passer une connexion de base de données PDO; pour cette raison, vous devrez aussi regarder la section sur le PDO.

Le travail de DAS Relationnel est de déplacer les données entre les applications et une base de données relationnelle. Afin de faire cela, vous devez dire quelle sorte de données vont être transférées entre les entités de base de données - tables, colonnes, clés primaires et clés étrangères - et les éléments de modèle SDO - types, propriétés, relations de retenue et ainsi de suite. Vous spécifiez ces informations comme des méta-données lorsque vous construisez le DAS Relationnel.

Vue d'ensemble des Opérations

1. La première étape est d'appeler le constructeur de DAS Relationnel, en lui passant les méta-données qui définissent les relations entre la base de données et le modèle SDO. Il y a des exemples plus bas.

2. L'étape suivante devrait être l'appel des méthodes executeQuery() ou executePreparedQuery() sur le DAS Relationnel, en leur passant soit une requête SQL littérale pour le DAS pour préparer et exécuter ou une requête préparée avec des paramètres fictifs et une liste des valeurs à être insérées. Vous pouvez aussi avoir besoin de spécifier un peu de méta-données à propos de la requête, ainsi le DAS Relationnel saura exactement quelles colonnes seront retournées de la base de données et dans quel ordre. Vous devez aussi passer une connexion de base de données PDO.

   La valeur de retour de executeQuery() ou executePreparedQuery() est un graphique de données normalisé contenant toutes les données du jeu de résultats. Pour une requête qui retourne les données obtenues à partir de plusieurs tables, ce graphique contiendra plusieurs objets de données, liés avec les relations SDO contenues. Il pourrait aussi y avoir des données de références qui ne sont pas de contenues à l'intérieur des données.

   Une fois que la requête a été exécutée et le graphique de données construit, il n'est pas nécessaire pour l'instance de DAS Relationnel ou pour la connexion de base de données. Il n'y a pas de verrou gardé sur la base de données. Le DAS Relationnel et la connexion de base de données PDO peuvent être toutes deux passés au ramasse miettes.

3. Il est probable que les données dans le graphique de données passent par plusieurs modifications. Le graphique de données peut être sérialisé dans une session PHP et ainsi peut avoir une vie au-delà d'une interaction client-serveur. Les objets de données peuvent être créés et ajoutés au graphique, les objets de données déjà dans le graphique peuvent être supprimés et les objets de données dans le graphique peuvent être modifiés.

4. Enfin, les changements effectués sur le graphique de données peuvent être appliqués à la base de donnés en utilisant la méthode applyChanges() de DAS Relationnel. Pour cela, une autre instance de DAS Relationnel doit être construite, en utilisant les mêmes méta-données, et une autre connexion à la base de données obtenue. La connexion et le graphique de données sont passés à applyChanges(). À ce point, le DAS Relationnel examine les changements et génère les requêtes SQL INSERT, UPDATE et DELETE nécessaires pour appliquer les changements. Toutes les requêtes UPDATE et DELETE sont qualifiées avec les valeurs originales des données, donc il se peut que les données aillent changées dans la base de données en attendant que les données soient détectées. En assumant qu'aucune collision de ce type ne s'est produite, les changements seront envoyés à la base de données. L'application peut alors continuer à travailler avec le graphique de données, effectuer d'autres changements et les appliquer, ou peut le jeter.

Il y a d'autres moyens de travailler avec les données dans la base de données : il est possible de créer simplement les objets de données et les écrire à la base de données sans effectuer d'appel préliminaire à executeQuery(), par exemple. Ce scénario et les autres sont explorés dans les exemples de la section plus bas.

# Installation

Les instructions d'installation pour tous les composants SDO sont dans la section d'installation de la documentation SDO.

Dans tous les cas, les faits essentiels sont que le DAS Relationnel est écrit en PHP et devrait être placé quelque part dans le include_path de PHP.

Votre application devra bien sur inclure le DAS Relationnel avec une ligne comme cela :

`<?php require_once 'SDO/DAS/Relational.php'; ?>`

# Pré-requis

Le DAS Relationnel requière que l'extension SDO soit installée. L'extension SDO requière une version de PHP 5.1 et le DAS Relationnel requière une version récente qui contient une mise à jour importante de PDO. Les informations les plus à jours à propos des niveaux requis de PHP devrait être trouvées dans le changelog pour ce paquetage sur PECL. Au moment que nous écrivons cette documentation, le DAS Relationnel requière le plus récent niveau de bêta de PHP 5.1, qui est PHP 5.1.0b3.

Le DAS Relationnel utilise le PDO pour accéder à une base de données relationnelle et devrait fonctionner avec une variété différente de bases de données. Au moment que nous écrivons cette documentation, cela a été testé avec les configurations suivantes

- MySQL 4.1.14, sur Windows. Le DAS Relationnel opère correctement avec le pilote php_pdo_mysql qui vient avec les programmes pré-configurés binaires de PHP 5.1.0b3.

- MySQL 4.1.13, sur Linux. Il est nécessaire d'avoir le plus récent pilote de PDO pour MySQL, qui vient avec un PHP. 5.1.0b3. Il se peut qu'il soit nécessaire de désinstaller les pilotes utilisés qui seraient venus de PECL en utilisant pear uninstall pdo_mysql . Vous devrez configurer votre PHP avec l'option --with-pdo-mysql.

- DB2 8.2 Édition Personnelle, sur Windows. Le DAS Relationnel opère correctement avec le pilote php_pdo_odbc qui vient avec les programmes pré-configurés binaires de PHP 5.1.0b3.

- DB2 8.2 Édition Personnelle de Développeur, sur Linux. L'édition e Développeur est requise puisqu'elle contient les fichiers d'inclusion requis lorsque PHP est configuré et bâti. Vous devrez configurer PHP avec l'option --with-pdo-odbc=ibm-db2.

Le DAS Relationnel applique les changements à la base de données à l'intérieur de transactions délimitées par l'utilisateur : cela appel la méthode PDO::beginTransaction() avant de commencer à appliquer les changements et PDO::commit() ou PDO::rollback() lorsque c'est complété. Peu importe la base de données qui est choisie, la base de données et le pilote PDO pour cette base de données doivent supporter ces appels.

# Limitations

Il y a les limitations suivantes dans la version courante de DAS Relationnel :

- Aucun support pour les données `NULL`. Il n'y a pas de support pour les types de SQL NULL. Cela n'est pas légal d'assigner une donnée PHP NULL à une propriété d'objet de données et le DAS Relationnel n'écriera pas en tant que NULL à la base de données. Si des données `NULL` sont trouvées dans la base de données dans une requête, la propriété restera non fixée.

- Seulement deux types de relation SDO. Les méta-données décrient plus bas permettent le DAS Relationnel de modéliser seulement deux types de relation SDO : relations contenues de valeurs multiples et les références contenues de valeurs simples. Dans SDO, si une propriété décrit une relation simple ou de valeurs multiples, et si c'est contenu ou non contenu, elle est indépendante. La plage complète des possibilités que SDO autorise ne peut être défini au complet. Il peut y avoir des relations qui peuvent être utiles pour modéliser mais que l'implémentation courante ne peut gérer. Un exemple est de relation de simples valeurs contenues.

- Aucun support pour la plage complète des types de données SDO. Le DAS Relationnel définit des propriétés primitives dans le modèle SDO en tant qu'un type de chaîne de caractères. SDO définit un ensemble de types plus riche contenant des types entier, valeur à virgule flottante, booléen et des données et de temps. Une chaîne de caractères est adéquate pour les buts de DAS Relationnel puisque la combinaison de PHP, PDO et les bases de données assurera que les valeurs passées en tant que chaînes de caractères seront converties au bon type avant d'être envoyées à la base de données. Cela affecte certains scénarios dans lesquels DAS Relationnel doit travailler avec un graphique de données qui est venu ou ira à un différent DAS.

- Seulement une clé étrangère par table. Les méta-données fournissent seulement le moyen de spécifier une clé étrangère par table. Cette clé étrangère peut établir une correspondance à un ou deux types de relations SDO supportés. Évidemment, il y a des scénarios qui ne peuvent être décrits sous cette limitation - il n'est pas possible d'avoir deux références non contenues d'une table à une autre par exemple.

# Exemples

Cette section illustre comment le DAS Relationnel peut être utilisé pour créer, récupérer, mettre â jour et supprimer des données dans une base de données relationnelle. Plusieurs de ces exemples sont illustrés avec trois tables dans une base de données qui contient "compagnies", "departements" à l'intérieur de ces compagnies et "employes" qui travaillent dans ces départements. Cet exemple est utilisé dans plusieurs places dans la littérature SDO. Voyez la section des exemples de spécification d'Objets de Service de Données ou la section d'exemples de la documentation de l'extension SDO.

Le DAS Relationnel est construit avec les méta-données qui définissent la base de données relationnelle et comment il devrait être en relation avec le SDO. La longue section qui suit décrit ces méta-données et comment construire le DAS Relationnel. Ces exemples qui suivent assument tous que ces méta-données sont inclues dans un fichier PHP.

Les exemples ci-dessous et les autres peuvent être trouvé dans le dossier `Scenarios` dans le paquetage DAS Relationnel.

Le DAS Relationnel émet des exceptions dans le cas qu'il trouve des erreurs dans les méta-données ou des erreurs lors de l'exécution des requêtes SQL à la base de données. Pour rendre les exemples plus concis, ils n'incluent pas les blocs try/catch autour des appels de DAS Relationnel.

Ces exemples diffèrent tous de l'utilisation prévue de SDO dans deux égards importants.

Premièrement, ils montrent toutes les interactions avec la base de données complétés dans un script. Ces scénarios ne sont pas réalistes mais sont choisis dans le but d'illustrer simplement l'utilisation de DAS Relationnel. Il est prévu que les interactions avec la base de données soient séparés dans le temps et le graphique de données sérialisés et désérialisé dans une session PHP une ou plusieurs fois tant que l'application interagit avec l'utilisateur final.

Deuxièmement, toutes les requêtes exécutées sur la base de données sont figées dans le code sans aucune substitution de variable. Dans ce cas, il est plus sage d'utiliser le simple appel de executeQuery() et c'est ce que montrent les exemples. En pratique, il est peu probable que la requête SQL soit connue entièrement avant son exécution. Afin d'autoriser la substitution sans danger des variables dans les requêtes SQL, sans prendre le risque d'effectuer des injections SQL avec des effets inconnus, il est plus sécuritaire d'utiliser executePreparedQuery() qui prend une requête SQL préparée contenant des paramètres fictifs et une liste des valeurs à être substituées.

## Spécification des méta-données

La première longue section décrit en détail comment les méta-données décrivant la base de données et le modèle SDO requis est fourni à DAS Relationnel.

Lorsque le constructeur de DAS Relationnel est appelé, il doit recevoir plusieurs informations. La majeure partie des informations, passée en tant qu'un tableau associatif dans le premier argument du constructeur, dit à DAS Relationnel ce qu'il doit savoir à propos de la base de données relationnelle. Il décrit les noms des tables, des colonnes, des clés primaires et des clés secondaires. On devrait comprendre assez facilement ce qui est requis et une fois écrit, il peut être placé dans un fichier PHP et inclut lorsque nécessaire. Le reste des informations, passé dans un deuxième et troisième arguments du constructeur, dit au DAS Relationnel ce qu'il doit savoir à propos des relations entre les objets et la forme du graphique de données; il détermine finalement comment les données de la base de données seront normalisées dans le graphique.

### Méta-données de base de données

Le premier argument du constructeur décrit la base de données relationnelle cible.

Chaque table est décrite par un tableau associatif avec jusqu'à quatre clés.

Clé | Valeur
--- | ---
name | Le nom de la table.
columns | Un tableau listant les noms des colonnes, dans n'importe quel ordre.
PK | Le nom de la colonne contenant la clé primaire.

FK

Un tableau avec deux entrées, 'from' et 'to' (provenance et destination), qui définissent une colonne contenant la clé étrangère et une table dans lequel la clé étrangère pointe. S'il n'y a pas de clé étrangère dans la table, alors l'entrée 'FK' est optionnelle. Seulement une clé étrangère peut être spécifiée. Seulement une clé étrangère pointant à une clé primaire d'une table peut être spécifiée.

`<?php
/*****************************************************************
* MÉTA-DONNÉES DÉFINISSANT LA BASE DE DONNÉES
******************************************************************/
$compagnie_table = array (
'name' => 'compagnie',
'columns' => array('id', 'nom', 'employe_du_mois'),
'PK' => 'id',
'FK' => array (
'from' => 'employe_du_mois',
'to' => 'employe',
),
);
$department_table = array (
'name' => 'department',
'columns' => array('id', 'nom', 'emplacement', 'nombre', 'co_id'),
'PK' => 'id',
'FK' => array (
'from' => 'co_id',
'to' => 'compagnie',
)
);
$employe_table = array (
'name' => 'employe',
'columns' => array('id', 'nom', 'SN', 'gestionnaire', 'dept_id'),
'PK' => 'id',
'FK' => array (
'from' => 'dept_id',
'to' => 'department',
)
);
$database_metadata = array($compagnie_table, $department_table, $employe_table);
?>`

Les méta-données correspondent à une base de données relationnelle qui peut avoir été définie comme étant MySQL :

    create table compagnie (
       id integer auto_increment,
       nom char(20),
       employe_du_mois integer,
       primary key(id)
     );
     create table department (
       id integer auto_increment,
       nom char(20),
       emplacement char(10),
       nombre integer(3),
       co_id integer,
       primary key(id)
     );
     create table employe (
       id integer auto_increment,
       nom char(20),
       SN char(4),
       gestionnaire tinyint(1),
       dept_id integer,
       primary key(id)
     );

ou comme DB2 :

    create table compagnie ( \
        id integer not null generated by default as identity,  \
        nom varchar(20), \
        employe_du_mois integer, \
        primary key(id) )
    create table department ( \
        id integer not null generated by default as identity, \
        nom varchar(20), \
        emplacement varchar(10), \
        nombre integer, \
        co_id integer, \
        primary key(id) )
    create table employe ( \
        id integer not null generated by default as identity, \
        nom varchar(20), \
        SN char(4), \
        gestionnaire smallint, \
        dept_id integer, \
        primary key(id) )

Notez que bien que dans cet exemple n'a pas de clé étrangère de spécifiée à la base de données et que la base de données n'est pas prévue à forcer l'intégrité référentielle, l'intention derrière la colonne co_id de la table departement et la colonne dept_id de la table employe est qu'elles pourraient contenir la clé primaire de leur compagnie les contenant ou l'enregistrement du département, respectivement. Alors ces deux colonnes actent comme des clés étrangères.

Il y a une troisième clé étrangère dans cet exemple, elle est de la colonne employe_du_mois de la table compagnie qui est compris dans une ligne de la table employe. Notez la différence dans l'intention entre cette clé étrangère et les deux autres. La colonne employe_du_mois représente une relation de valeurs simples : il peut y avoir seulement un employé du moi pour une compagnie donnée. Les colonnes co_id dept_id représentent des relations de valeurs multiples : une compagnie peut contenir plusieurs département et un département peut contenir beaucoup d'employés. Cette distinction deviendra évidente lorsque le reste des méta-données sélectionne les relations entre la compagnie-département et le département-employé comme étant une relation contenue.

Il y a un peu de règles simples qui doivent être suivies lorsque l'on construit les méta-données de base de données :

- Toutes les tables doivent avoir des clés primaires et les clés primaires doivent être spécifiées dans les méta-données. Sans clés primaires, il n'est pas possible de garder une trace des identités des objets. Comme vous pouvez le voir avec les requête SQL qui créent les tables, les clés primaires peuvent être générées automatiquement, ce qui signifie, qu'elles sont générées et assignées par la base de données lorsque l'enregistrement est inséré. Dans ce cas, la clé primaire générée automatiquement est obtenue de la base de données et insérées dans l'objet de données immédiatement après que la ligne soit insérée dans la base de données.

- Il n'est pas nécessaire de spécifier les méta-données de toutes les colonnes qui existent dans la base de données, seulement celles qui seront utilisées. Par exemple, si la table compagnie avait un autre colonne que l'application ne souhaite pas accéder avec SDO, il n'est pas nécessaire de la spécifiée dans les méta-données. En contrepartie, cela ne devrait pas causer de problème de la spécifier : si elle est spécifiée dans les méta-données mais jamais récupérée ou assignée par l'application, alors la colonne inutilisée ne devrait rien affecter.

- Dans les méta-données de base de données, notez que les définitions des clés étrangères n'identifient pas la colonne de destination dans la table qui est pointée, mais le nom de la table elle-même. Strictement, le modèle relationnel permet la destination d'une clé étrangère à être une clé non primaire. Seules les clés étrangères qui pointent à une clé primaire sont utiles pour la construction du modèle SDO, puisque les méta-données spécifient le nom de la table. Il est entendu que la clé étrangère pointe vers la clé primaire d'une table donnée.

Ayant donné ces règles et les requêtes SQL qui définissent les bases de données, les méta-données de base de données devrait être faciles à construire.

#### Que fait DAS Relationnel avec ces méta-données

Le DAS Relationnel utilise les méta-données de base de données pour former la plupart des modèles SDO. Pour chaque table dans les méta-données de base de données, un type SDO est défini. Chaque colonne qui peut représenter une valeur primitive (les colonnes qui ne sont pas définies comme étant des clés étrangères) est ajoutée comme propriété au type SDO.

Toutes les propriétés primitives sont données par un type de chaîne de caractères dans le modèle SDO, sans se soucier de leur type SQL. Lors de la ré-écriture des données dans la base de données, le DAS Relationnel créera une requête SQL qui traitera les valeurs comme étant des chaînes de caractères et la base de données les convertira dans le type approprié.

Les clés étrangères sont interprétées de une des deux manières, dépendamment des méta-données contenues dans le troisième argument du constructeur qui définissent les relations de SDO contenues. Une discussion de cela est donc reportée dans la section relations SDO contenues ci-dessous.

### Spécification du type de racine de l'application

Le second argument du constructeur est l'application du type de racine. La vraie racine de chaque graphique de données est un objet d'un type de racine spécial et tous les objets de données des applications viennent quelque part sous cela. De la plupart des types d'application dans le modèle SDO, une doit être le type d'application immédiatement sous la racine du graphique de données. S'il y a seulement une table dans les méta-données de base de données, le type de racine de l'application peut être impliqué et cet argument peut être omis.

### Spécification des relations SDO contenues

Le troisième argument du constructeur définit comment les types dans le modèle seront liés ensemble pour former un graphique. Cela identifie les relations parent-enfant entre les types qui collectivement forment un graphique. Les relations doivent être supportées par les clés étrangères pour être trouvées dans les données, d'une manière rapide d'être décrit.

Les méta-données sont un tableau contenant un ou plusieurs tableaux associatifs, chacun d'eux identifie un parent et un enfant. L'exemple ci-dessous montre une relation parent-enfant de compagnie au département et un autre du département aux employés. Chacune d'elles deviendra un propriété définissant une relation de valeur multiples contenue dans un modèle SDO.

`<?php $department_containment = array( 'parent' => 'compagnie', 'child' => 'department'); $employee_containment = array( 'parent' => 'department', 'child' => 'employe'); $SDO_containment_metadata = array($department_containment, $employee_containment); ?>`

Les clés étrangères dans les méta-données de base de données sont interprétées comme des propriétés avec soit des relations de valeurs multiples contenues ou des références de simples valeurs non contenues, dépendamment si elles ont une relation SDO contenue correspondante spécifiée dans les méta-données. Dans cet exemple ici, les clés étrangères du département à la compagnie (la colonne co_id dans la table de departement) et de l'employé au département (la colonne dept_id dans la table employe) sont interprétées comme supportant les relations SDO contenues. Chaque référence contenue mentionnée dans les méta-données de relations contenue de SDO doit avoir une clé correspondante présente dans la base de données et définie dans les méta-données de base de données. Les valeurs des colonnes de la clé étrangère pour les relations contenues n'apparaissent pas dans les objets de données; à la place, chacune d'entre elles est représentée par une relation contenue du parent à l'enfant. Alors la colonne co_id dans la ligne de département de la base de données, par exemple, n'apparaît pas en tant que propriété du type de département, mais apparaît à la place comme une relation contenue appelée departname sur le type de compagnie. Notez que la clé étrangère et la relation parent-enfant semble avoir un sens opposé : la clé étrangère pointe du département à la compagnie, mais la relation parent-enfant pointe de la compagnie au département.

La troisième clé dans cet exemple, le employe_du_mois , est gérée différemment. Elle n'est pas mentionnée dans les méta-données de relations SDO contenues. Ceci a pour conséquence d'être interprété de la seconde manière : elle devient une référence de valeur simple non contenue sur l'objet compagnie, sur lequel vous pouvez assigner des références au type d'employé d'objets de données SDO. Elle apparaît comme une propriété du type de compagnie. Le moyen pour lui assigner une valeur dans le graphique de données est d'avoir un graphique qui contient un objet employé avec les relations contenues et d'assigner l'objet à celui-ci. Ceci est montré dans les exemples plus loin.

## Exemples avec une table

Les exemples suivants utilisent tous le DAS Relationnel pour travailler avec un graphique de données contenant juste un objet de données d'application, une seule compagnie et les données qui seront dans la table compagnie. Ces exemples ne montre pas le pouvoir de SDO ou de DAS Relationnel et bien sûr les mêmes résultats peuvent être atteints plus économiquement à l'aide de requêtes SQL directes mais ces exemples sont pour vous montrer comment fonctionne le DAS Relationnel.

Pour ce simple scénario, il serait possible de simplifier les méta-données de base de données pour inclure juste la table de compagnie - si cela était fait, le deuxième et troisième argument du constructeur et le spécificateur de colonne utilisé dans l'exemple de requête deviendrait optionnel.

Exemple 1. Création d'un objet de données

Le plus simple exemple est de créer un objet de données simple et de l'écrire à la base de données. Dans cet exemple, un objet simple de compagnie est créé, son nom est fixé à 'Acme' et le DAS Relationnel est appelé pour écrire les changements à la base de données. Le nom de la compagnie est fixé ici en utilisant la méthode de propriété de nom. Voyez la section d'exemples sur l'extension SDO pour d'autres moyens d'accéder au propriétés d'un objet.

Les objets de données peuvent seulement être créés lorsque vous avez un objet de données au démarrage. C'est pour cette raison que le premier appel à DAS Relationnel ici est pour obtenir l'objet racine. C'est en effet comment demander pour un graphique de données vide - l'objet de racine spécial est la vrai racine de l'arbre. L'objet de données compagnie est alors créé avec l'appel à createDataObject() sur l'objet racine. Ceci crée l'objet de données compagnie et l'insère dans le graphique en insérant une propriété de valeurs multiples contenue dans l'objet racine appelé 'compagnie'.

Lorsque DAS Relationnel est appelé pour effectuer les changements, une simple requête d'insertion 'INSERT INTO compagnie (nom} VALUES ("Acme");' sera construite et exécutée. La clé primaire générée automatiquement sera fixée dans l'objet de données et le changement sera effacé, alors il serait possible de continuer de travailler avec le même objet de données, le modifier, et applique les nouveaux changements une deuxième fois.

`<?php
require_once 'SDO/DAS/Relational.php';
require_once 'company_metadata.inc.php';
/**************************************************************
* Construit le DAS avec les méta-données
***************************************************************/
$das = new SDO_DAS_Relational ($database_metadata,'compagnie',$SDO_containment_metadata);
/**************************************************************
* Obtient l'objet racine et crée un objet compagnie dessous.
* Effectue un petit changement à l'objet de données.
***************************************************************/
$root = $das -> createRootDataObject();
$acme = $root -> createDataObject('compagnie');
$acme->name = "Acme";
/**************************************************************
* Récupère la connexion à la base de données et écrit l'objet à la base de données
***************************************************************/
$dbh = new PDO(PDO_DSN,DATABASE_USER,DATABASE_PASSWORD);
$das -> applyChanges($dbh, $root);
?>`

Exemple 2. Récupération d'un objet de données

Dans cet exemple, un simple objet de données est récupéré de la base de données - ou possiblement plus d'un s'il y avait plus d'une compagnie qui était appelée 'Acme'. Pour chaque compagnie retournée, les propriétés nom et id sont affichées.

Dans cet exemple, le troisième argument de executeQuery(), le spécificateur de colonne est requis puisqu'il y a d'autres tables dans les méta-données avec le nom de colonne nom et id. S'il n'y avait pas d'ambiguïté possible, il aurait pu être omis.

`<?php
require_once 'SDO/DAS/Relational.php';
require_once 'company_metadata.inc.php';
/**************************************************************
* Construit le DAS avec les méta-données
***************************************************************/
$das = new SDO_DAS_Relational ($database_metadata,'compagnie',$SDO_containment_metadata);
/**************************************************************
* Récupère la connexion à la base de données
***************************************************************/
$dbh = new PDO(PDO_DSN,DATABASE_USER,DATABASE_PASSWORD);
/**************************************************************
* Effectue une requête pour obtenir un objet compagnie - possiblement
* plusieurs s'ils existent
***************************************************************/
$root = $das->executeQuery($dbh,
'select nom, id from compagnie where nom="Acme"',
array('compagnie.nom', 'compagnie.id') );
/**************************************************************
* Affiche le nom et le id
***************************************************************/
foreach ($root['compagnie'] as $compagnie) {
echo "La compagnie obtenue de la base de données a le nom = " .
$compagnie['nom'] . " et un id " . $compagnie['id'] . "\n";
}
?>`

Exemple 3. Mise à jour d'objet de données

Cet exemple combine les deux précédent, dans le sens que pour être mis à jour, l'objet doit être premièrement récupéré. L'application renverse le nom de compagnie (alors 'Acme' devient 'emcA') et alors les changements sont écrits à la base de données de la même manière qu'ils étaient lorsque l'objet avait été créé. Puisque la requête cherche pour le nom, on peut chercher des deux manières le nom à plusieurs reprises pour trouver la compagnie et renverser son nom chaque fois.

Dans cet exemple, la même instance de DAS Relationnel est réutilisée pour applyChanges(), avec le descripteur de base de données PDO. Ceci est tout à fait correcte; il est aussi possible d'autoriser les instances précédentes d'être ramassées par le ramasse-miettes et d'obtenir de nouvelles instances. Aucune données d'état concernant le graphique n'est tenue par le DAS Relationnel une fois qu'il a retourné un graphique de données à l'application. Toutes les données nécessaires sont soit dans le graphique ou peuvent être reconstruites à partir des méta-données.

`<?php
require_once 'SDO/DAS/Relational.php';
require_once 'company_metadata.inc.php';
/**************************************************************
* Construit le DAS avec les méta-données
***************************************************************/
$das = new SDO_DAS_Relational ($database_metadata,'compagnie',$SDO_containment_metadata);
/**************************************************************
* Récupère la connexion à la base de données
***************************************************************/
$dbh = new PDO(PDO_DSN,DATABASE_USER,DATABASE_PASSWORD);
/**************************************************************
* Effectue une requête pour obtenir un objet compagnie - possiblement
* plusieurs s'ils existent
***************************************************************/
$root = $das->executeQuery($dbh,
'select nom, id from compagnie where nom="Acme" or nom="emcA"',
array('compagnie.nom', 'compagnie.id') );
/**************************************************************
* Modifie le nom de la première compagnie seulement
***************************************************************/
$compagnie = $root['compagnie'][0];
echo "Compagnie obtenue avec le nom " . $compagnie->nom . "\n";
$compagnie->nom = strrev($compagnie->nom);
/**************************************************************
* Écriture du changement
***************************************************************/
$das->applyChanges($dbh,$root);
?>`

Exemple 4. Suppression d'un objet de données

Toutes compagnies appelées 'Acme' ou son inverse 'emcA' sont récupérées. Elles sont ensuite toutes supprimées du graphique avec unset.

Dans l'exemple, elles sont toutes supprimées en un seul coup en supprimant la propriété contenue (la propriété définissant la relation contenue). Il est aussi possible de les supprimer individuellement.

`<?php
require_once 'SDO/DAS/Relational.php';
require_once 'company_metadata.inc.php';
/**************************************************************
* Construit le DAS avec les méta-données
***************************************************************/
$das = new SDO_DAS_Relational ($database_metadata,'compagnie',$SDO_containment_metadata);
/**************************************************************
* Récupère la connexion à la base de données
***************************************************************/
$dbh = new PDO(PDO_DSN,DATABASE_USER,DATABASE_PASSWORD);
/**************************************************************
* Effectue une requête pour obtenir un objet compagnie - possiblement
* plusieurs s'ils existent
***************************************************************/
$root = $das->executeQuery($dbh,
'select nom, id from compagnie where nom="Acme" or nom="emcA"',
array('company.name', 'company.id') );
/**************************************************************
* Supprime les compagnies trouvées du graphique de données
***************************************************************/
unset($root['compagnie']);
/**************************************************************
* Écrit le(s) changement(s)
***************************************************************/
$das->applyChanges($dbh,$root);
?>`

## Exemples avec deux tables

Les exemples suivants utilisent tous deux tables de la base de données compagnie : les tables compagnie et departement. Ces exemples montrent plus le fonctionnement de DAS Relationnel.

Dans cette série d'exemples, une compagnie et un département son créé, récupéré, mis à jour et finalement supprimé. Ceci montre le cycle de vie pour un graphique de données contenant plus d'un objet. Notez que cet exemple vide les tables compagnie et departement au démarrage, ainsi les résultats exacts des requêtes peuvent être connus.

Vous pouvez trouvez ces exemples combinés dans un script appelé `1cd-CRUD` dans le répertoire `Scenarios` du paquetage DAS Relationnel.

Exemple 5. Une compagnie, un département - Création

Comme dans l'exemple précédent où l'on créait juste un objet de données de compagnie, la première action après la construction du DAS Relationnel est d'appeler createRootDataObject() pour obtenir l'objet racine spécial du graphique de données vide. L'objet compagnie est alors créé en tant que fils de cet objet racine, et l'objet departement en tant que fils de l'objet compagnie.

Lorsqu'il est venu le temps d'appliquer les changements, le DAS Relationnel doit effectuer des traitements spéciaux pour maintenir la clé étrangère qui supporte les relations contenues, en particulier si une clé primaire générée automatiquement est en jeu. Dans cet exemple, les relations entre la clé primaire générée automatiquement id dans la table compagnie et la colonne co_id dans la table departement doivent être maintenues. Lors de l'insertion de la compagnie et du département pour la première fois, le DAS Relationnel doit premièrement insérer une ligne de compagnie, ensuite appeler la méthode de PDO getLastInsertId() pour obtenir la clé primaire générée automatiquement, et ensuite ajouter la valeur à la colonne co_id lors de l'insertion de la ligne departement.

`<?php
require_once 'SDO/DAS/Relational.php';
require_once 'company_metadata.inc.php';
/*************************************************************************************
* Vidage des deux tables
*************************************************************************************/
$dbh = new PDO(PDO_DSN,DATABASE_USER,DATABASE_PASSWORD);
$pdo_stmt = $dbh->prepare('DELETE FROM COMPAGNIE;');
$rows_affected = $pdo_stmt->execute();
$pdo_stmt = $dbh->prepare('DELETE FROM DEPARTEMENT;');
$rows_affected = $pdo_stmt->execute();
/**************************************************************
* Crée une compagnie avec le nom Acme et un département, département de Chaussure
***************************************************************/
$dbh = new PDO(PDO_DSN,DATABASE_USER,DATABASE_PASSWORD);
$das = new SDO_DAS_Relational ($database_metadata,'compagnie',$SDO_containment_metadata);
$root = $das -> createRootDataObject();
$acme = $root -> createDataObject('compagnie');
$acme -> nom = "Acme";
$chaussure = $acme->createDataObject('departement');
$chaussure->nom = 'Chaussure';
$das -> applyChanges($dbh, $root);
?>`

Exemple 6. Une compagnie, un département - Récupération et Mise à jour

Dans ce cas, la requête SQL passé à executeQuery() exécute un inner join pour joindre les données des tables compagnie et departement. Les clés primaires pour les tables compagnie et departement doivent être inclues dans la requête. Le jeu de résultats est normalisé de nouveau pour former un graphique de données normalisé. Notez que le spécificateur de colonne est passé en troisième argument de l'appel executeQuery() qui autorise DAS Relationnel de savoir quelle colonne est laquelle dans le jeu de résultats.

Notez que la colonne co_id bien qu'utilisée dans la requête n'est pas requis dans le jeu de résultats. Afin de comprendre que fait DAS Relationnel lorsqu'il construit le graphique de données, il peut être utile de visualiser à quoi ressemble les jeu de résultats. Bien que les données dans la base de données sont normalisée, alors plusieurs lignes de département peuvent pointer vers la clé étrangère d'une ligne de compagnie, les données dans le jeu de résultats sont non-normalisée : c'est, s'il y a une compagnie et de multiples département, les valeurs pour la compagnie qui sont répétées à chaque ligne. Le DAS Relationnel doit renverser ce processus et retourner le jeu de résultats dans un graphique normalisé, avec seulement un objet compagnie.

Dans cet exemple, le DAS Relationnel examine le jeu de résultats et le spécificateur de colonne, trouve les données pour les tables compagnie et departement, trouve les clés primaires pour les deux et interprète chaque ligne comme contenant des données d'un département et comme parent compagnie. S'il n'a pas vue de données de la compagnie auparavant (il utilise la clé primaire pour vérifier), il crée un objet compagnie et ensuite l'objet compagnie sous lui. S'il a vu des données pour la compagnie avant et a déjà créé l'objet compagnie, il crée simplement l'objet departement sous lui.

De cette manière, le DAS Relationnel peut récupérer et normaliser de nouveau les données pour de multiples compagnies et de multiples départements sous ceux-ci.

`<?php
require_once 'SDO/DAS/Relational.php';
require_once 'company_metadata.inc.php';
/**************************************************************
* Récupération de la compagnie et du département de Chaussure, ensuite
* supprime Chaussure et ajoute IT
***************************************************************/
$dbh = new PDO(PDO_DSN,DATABASE_USER,DATABASE_PASSWORD);
$das = new SDO_DAS_Relational ($database_metadata,'compagnie',$SDO_containment_metadata);
$root = $das->executeQuery($dbh,
'select c.id, c.nom, d.id, d.nom from compagnie «c, departement d where d.co_id = c.id',
array('compagnie.id','compagnie.nom','departement.id','departement.nom'));
$acme = $root['compagnie'][0]; // récupère la première compagnie - sera 'Acme'
$chaussure = $acme['departement'][0]; // récupère le premier département en dessous - sera 'Chaussure'
unset($acme['departement'][0]);
$it = $acme->createDataObject('departement');
$it->name = 'IT';
$das -> applyChanges($dbh, $root);
?>`

Exemple 7. Une compagnie, deux départements - Récupération et Suppression

Dans cet exemple, la compagnie et le département sont récupérés et ensuite supprimés. Il n'est pas nécessaire de les supprimer individuellement (bien que cela est possible) - la suppression de l'objet compagnie du graphique de données supprime aussi tous les départements sous lui.

Notez le moyen de l'objet compagnie est actuellement supprimé en utilisant l'appel unset de PHP. La suppression doit être effectuée sur la propriété qui est dans ce cas la propriété de compagnie sur l'objet racine spécial. Vous devez utiliser :

`<?php unset($root['compagnie'][0]); ?>`

et non pas :

`<?php unset($acme); // FAUX ?>`

La suppression de $acme détruira simplement la variable mais laissera les données dans le graphique intacte.

`<?php
require_once 'SDO/DAS/Relational.php';
require_once 'company_metadata.inc.php';
/**************************************************************
* Récupération de la compagnie et du département IT, ensuite supprime la
* compagnie entière
***************************************************************/
$dbh = new PDO(PDO_DSN,DATABASE_USER,DATABASE_PASSWORD);
$das = new SDO_DAS_Relational ($database_metadata,'compagnie',$SDO_containment_metadata);
$root = $das->executeQuery($dbh,
'select c.id, c.nom, d.id, d.nom from compagnie c, departement d where d.co_id = c.id',
array('compagnie.id','compagnie.nom','departement.id','departement.nom'));
$acme = $root['compagnie'][0];
$it = $acme['departement'][0];
unset($root['compagnie'][0]);
$das -> applyChanges($dbh, $root);
?>`

## Exemple avec trois tables

Les exemples suivant utilisent tous trois tables de la base de données compagnie : les tables compagnie, departement et employe. Elles introduisent le dernier morceau du fonctionnement non expliqué dans les exemples ci haut : la référence non contenue employe_du_mois.

Comme les exemples ci haut pour la compagnie et le département, la série d'exemples illustre le cycle de vie complet d'un graphique de données.

Exemple 8. Une compagnie, un département, un employé - Création

Dans cet exemple, une compagnie est créée contenant un département et seulement un employé. Notez que dans cet exemple, les trois tables sont vidées à leur démarrage ainsi les résultats exacts des requêtes peuvent être connus.

Notez comment une fois que la compagnie, le département et l'employé est créé que la propriété employe_du_mois de la compagnie peut être faite pour pointer au nouvel employé. Puisque c'est une référence qui n'est pas contenue, ceci ne peut être effectué tant que l'objet employé ait été créé dans le graphique. Les références non contenues doivent être gérées prudemment. Par exemple, si un employé est maintenant supprimé de son département, il ne serait pas correcte d'essayer de sauver le graphique sans premièrement effacer ou réassigner la propriété employe_du_mois . Cette règle des graphiques de données SDO requière que tous les objets pointé par une référence qui n'est pas contenue doit être aussi accessible par des relations contenues.

Lorsque vient le moment d'insérer le graphique dans la base de données, la procédure est similaire à l'exemple d'insertion d'une compagnie et d'un département, cependant, la propriété employe_du_mois introduit une plus grande complexité. Le DAS Relationnel doit insérer les objets en descendant l'arbre formée des relations contenues, donc la compagnie, ensuite le département et ensuite l'employée. Ceci est nécessaire puisqu'il y a toujours une clé primaire générée automatiquement du parent pour l'inclure dans une ligne du fils. Mais lorsque la compagnie est insérée, l'employée qui est l'employé du mois n'est pas encore inséré et la clé primaire est inconnue. La procédure est qu'après l'insertion de l'employé et que sa clé primaire soit connue, une dernière étape est effectuée qui permet de modifier la compagnie avec la clé primaire de l'employé.

`<?php
require_once 'SDO/DAS/Relational.php';
require_once 'company_metadata.inc.php';
/*************************************************************************************
* Vidage des deux tables
*************************************************************************************/
$dbh = new PDO(PDO_DSN,DATABASE_USER,DATABASE_PASSWORD);
$pdo_stmt = $dbh->prepare('DELETE FROM COMPAGNIE;');
$rows_affected = $pdo_stmt->execute();
$pdo_stmt = $dbh->prepare('DELETE FROM DEPARTEMENT;');
$rows_affected = $pdo_stmt->execute();
$pdo_stmt = $dbh->prepare('DELETE FROM EMPLOYE;');
$rows_affected = $pdo_stmt->execute();
/*************************************************************************************
* Crée une compagnie minuscule mais complète.
* Le nom de la compagnie est Acme.
* Il y a un département, Chaussure.
* Il y a une employé, Bob.
* L'employé du mois est Bob.
*************************************************************************************/
$das = new SDO_DAS_Relational ($database_metadata,'compagnie',$SDO_containment_metadata);
$dbh = new PDO(PDO_DSN,DATABASE_USER,DATABASE_PASSWORD);
$root = $das -> createRootDataObject();
$acme = $root -> createDataObject('compagnie');
$acme -> nom = "Acme";
$chaussure = $acme -> createDataObject('departement');
$chaussure -> nom = 'Chaussure';
$chaussure -> emplacement = 'Bloc-A';
$bob = $chaussure -> createDataObject('employe');
$bob -> nom = 'Bob';
$acme -> employe_du_mois = $bob;
$das -> applyChanges($dbh, $root);
echo "Écriture de Acme avec un département et un employé\n";
?>`

Exemple 9. Une compagnie, un département, un employé - Récupération et Mise à Jour

La requête SQL passée à DAS Relationnel est cette fois un inner join qui récupère les données des trois tables. Autrement, cet exemple n'introduit rien de nouveau de l'exemple précédent

Le graphique est mis à jour avec l'addition d'un nouveau département et d'un nouvel employé et quelques modifications au propriétés de nom des objets existant dans le graphique. Les changements combinés sont écrits. Le DAS Relationnel traitera et appliquera un mélange arbitraire des additions, des modifications et des suppressions provenant et allant vers le graphique.

`<?php
require_once 'SDO/DAS/Relational.php';
require_once 'company_metadata.inc.php';
/*************************************************************************************
* Trouve la compagnie encore et change certains aspects.
* Change le nom de la compagnie, le département et l'employé.
* Ajoute un second département et un nouvel employé.
* Change l'employé du mois
*************************************************************************************/
$das = new SDO_DAS_Relational ($database_metadata,'compagnie',$SDO_containment_metadata);
$dbh = new PDO(PDO_DSN,DATABASE_USER,DATABASE_PASSWORD);
$root = $das->executeQuery($dbh,
"select c.id, c.nom, c.employe_du_mois, d.id, d.nom, e.id, e.nom " .
"from compagnie c, departement d, employe e " .
"where e.dept_id = d.id and d.co_id = c.id and c.nom='Acme'",
array('compagnie.id','compagnie.nom','compagnie.employe_du_mois',
'departement.id','departement.nom','employe.id','employe.nom'));
$acme = $root['compagnie'][0];
$chaussure = $acme->departement[0];
$bob = $chaussure -> employe[0];
$it = $acme->createDataObject('departement');
$it->nom = 'IT';
$it->location = 'Bloc-G';
$billy = $it->createDataObject('employe');
$billy->nom = 'Billy';
$acme->nom = 'MegaCorp';
$chaussure->nom = 'Footwear';
$sue->nom = 'Suzan';
$acme->employe_du_mois = $billy;
$das -> applyChanges($dbh, $root);
echo "Écriture de la compagnie avec un département en plus et un employé et
tous les noms ont changés Megacorp/Footwear/Suzan)\n";
?>`

Exemple 10. Une compagnie, deux départements, deux employés - Récupération et Suppression

La compagnie est récupéré en tant qu'un graphique de données complet contenant cinq objets de données - la compagnie, deux départements et deux employés. Ils sont tous supprimés en supprimant l'objet compagnie. La suppression d'un objet du graphique supprime tous les objets sous celui-ci dans le graphique. Cinq requêtes DELETE SQL sera générées et exécutée. Comme d'habitude, elles seront qualifiées avec une clause WHERE qui contient tous les champs qui ont été récupérés, alors toutes les mises à jour des données dans la base de données pendant ce temps par un autre processus seront détectées.

`<?php
require_once 'SDO/DAS/Relational.php';
require_once 'company_metadata.inc.php';
/*************************************************************************************
* Maintenant lit une ou plusieurs fois et supprime.
* Vous pouvez supprimer par partie, appliquer les changements, et ensuite
* continuer à travailler avec le même graphique de données mais la précaution
* est requise pour garder véracité - vous ne pouvez pas supprimer l'employé
* qui est l'employé du mois sans le réassigner. Pour plus de précaution ici,
* nous supprimons la compagnie en entier d'un seul coup.
*************************************************************************************/
$das = new SDO_DAS_Relational ($database_metadata,'compagnie',$SDO_containment_metadata);
$dbh = new PDO(PDO_DSN,DATABASE_USER,DATABASE_PASSWORD);
$root = $das->executeQuery($dbh,
"select c.id, c.nom, c.employe_du_mois, d.id, d.nom, e.id, e.nom " .
"from compagnie c, departement d, employe e " .
"where e.dept_id = d.id and d.co_id = c.id and c.nom='MegaCorp';",
array('compagnie.id','compagnie.nom','compagnie.employe_du_mois',
'departement.id','departement.nom','employe.id','employe.nom'));
$megacorp = $root['compagnie'][0];
unset($root['compagnie']);
$das -> applyChanges($dbh, $root);
echo "Suppression de la compagnie, des départements et des employés d'un seul coup.\n";
?>`

# Suivi

Vous pouvez être intéressé de voir les requêtes SQL qui sont générées afin d'appliquer les changements à la base de données. Dans le haut du fichier `SDO/DAS/Relational.php`, vous trouvez un certain nombre de constantes qui contrôle si le processus de construction et d'exécution des requêtes SQL doivent être suivies. Essayez la configuration DEBUG_EXECUTE_PLAN à `TRUE` pour voir les requêtes SQL générées.

# Classes pré-définies

Le DAS Relationnel fournit deux classes : le DAS Relationnel lui-même et aussi la sous-classe Exception qui peut être jetée. Le DAS Relationnel a quatre appels publics utiles : le constructeur, la méthode createRootDataObject() pour obtenir l'objet racine d'un graphique de données vide, la méthode executeQuery() pour obtenir le graphique de données contenant les données d'une base de données relationnelle et la méthode applyChanges() pour écrire les changements effectués au graphique de données vers la base de données relationnelle.

## SDO_DAS_Relational

Le seul autre objet que SDO_DAS_Relational_Exception que l'application pourrait interagir.

### Méthodes

- __construct - construit le DAS Relationnel avec le modèle dérivé des méta-données passées

- createRootDataObject - obtient le graphique de données vide contenant seulement l'objet racine spécial

- executeQuery - exécute une requête SQL passée en tant que chaîne de caractères littérale et retourne les résultats dans un graphique de données normalisé

- executePreparedQuery - exécute une requête SQL passée en tant que requête préparée, avec une liste de valeur à substituer pour les paramètres fictifs et retourne le résultats d'un graphique de données normalisé

- applyChanges - examine les changements dans le graphique de données et applique ces changements à la base de données, sujet d'une acceptation de simultanéité optimiste

## SDO_DAS_Relational_Exception

Est une sous-classe de la classe PHP Exception. Elle n'ajoute aucun comportement à Exception. Jetée, avec une explication utile, pour signaler les erreurs dans les méta-données ou des échecs non prévus pour exécuter des opérations SQL.

Précédent | Sommaire | Suivant
SDO_DAS_XML::saveDocumentToString | Niveau supérieur | SDO_DAS_Relational::applyChanges