wiki:CopixDAOFichierXML

Introduction

Rappels & Introduction du fichier XML

Avec CopixDAO, vous pouvez donc développer un DAO sans écrire une seule ligne de code PHP.

Vous pouvez choisir d'indiquer dans la factory le nom de la table (auquel cas Copix pourra générer automatiquement un DAO pour vous) ou choisir de spécifier un sélecteur de fichier XML, ce que nous allons expliquer ici.

Ce fichier XML doit être situé dans le répertoire des ressources (resources) et porter le nom nom_dao.dao.xml.

Ce fichier XML va vous permettre de déclarer le "mapping" entre l'objet DAO et une ou plusieurs tables en base de données, donc de dire que telle propriété de l'objet correspond à tel champ de telle table.

Un fichier de définition de DAO doit être enregistré dans le répertoire resources d'un module ou du projet. Il doit avoir comme nom : xxxxx.dao.xml, xxxxx étant le nom du DAO, que l'on indiquera en paramètre à certaines fonctions.

Le fichier XML de définition de DAO contient bien sûr une balise racine qui a pour nom daodefinition. Voici un début de ce fichier :

<?xml version="1.0" encoding="UTF-8" ?>
<daodefinition>
...
</daodefinition>

La balise daodefinition encadre trois sections différentes :

  • La déclaration de la source de données (connection, tables..)
  • La déclaration des propriétés
  • La déclaration (facultative) de méthodes supplémentaires de sélection

Dans quels cas ?

Dans quels cas pouvons-nous souhaiter utiliser un fichier XML plutôt qu'un DAO automatique (à partir du nom de la table) ?

  • Déclaration de méthodes supplémentaires (section methods)
  • Mapping limité par rapport aux champs
  • Déclaration de contraintes supplémentaires sur les champs
  • Fournir des informations supplémentaires sur les champs (leur "vrai" nom par exemple)
  • Réaliser des jointures

Fichier de définition XML

Section déclaration de la source de donnée

Cette section est délimitée par la balise datasource. Elle contient une balise facultative "connection", indiquant la connection CopixDB à utiliser, et la déclaration des tables, comme ceci :

<?xml version="1.0" encoding="UTF-8" ?>
<daodefinition>
   <datasource>
      <connection name="Select" />
      <tables>
         <table name="pers" tablename="personne_per" primary="yes" />
         <table name="ville" tablename="ville_vi" join="left" />
      </tables>
   </datasource>
</daodefinition>

Nous avons ici indiqué que le DAO doit utiliser la connexion ayant pour nom Select. Nous pouvons omettre la balise connection, et dans ce cas, le DAO utilisera la connexion déclaré par défaut dans CopixDB.

Nous indiquons ensuite que le DAO repose sur 2 tables, personne_per et ville_vi, qui sont liées par une jointure externe (left), la table personne_per étant la table principale (primary="yes")

À chacune des déclarations de table nous donnons un nom arbitraire, pers et ville qui seront utilisés dans la déclaration des propriétés. Ces noms serviront également d'alias dans les requêtes SQL générées.

L'attribut name est obligatoire. L'attribut tablename est facultatif, et vaut par défaut la valeur de l'attribut name. Il doit y avoir une et une seule déclaration de table qui contienne l'attribut primary avec la valeur yes (ou 1, ou true). L'attribut join est facultatif et vaut par défaut 'inner', les autres valeurs possibles étant 'left' et 'right'.

Section déclaration des propriétés

Cette section est délimitée par la balise properties, et contient un ensemble de balise property :

<?xml version="1.0"   encoding="UTF-8" ?>
<daodefinition>
   <datasource>...</datasource>
   <properties>
      <property ... />
      <property ... />
      <property ... />
      ...
   </properties>
</daodefinition>

Cette section permet de déclarer les propriétés du DAO, ainsi que le mapping avec les tables. Les attributs possibles pour la balise property sont les suivants.

  • name : nom de la propriété (obligatoire)
  • fieldname : nom du champs correspondant (Si absent, vaut par défaut la valeur de name)
  • table : nom (alias) de la table où se trouve le champs. Si cet attribut est omis, la table par défaut est celle déclarée comme primaire.
  • required : booléen indiquant si la propriété doit être non null.
  • pk : booléen indiquant si le champ correspondant à la propriété est une clé primaire
  • type : indique le type de donnée. Les valeurs possibles sont : integer (ou int), autoincrement, double (ou float), numeric (long entier) ou string (valeur par défaut).
  • fktable, fkfieldname : si ces attributs sont définis et non vides, ils indiquent que le champ est une clé étrangère. Ces deux attributs contiennent donc respectivement le nom de la table étrangère (valeur de l'attribut name de la balise <table /> correspondante) et celui du champ (le vrai nom du champ) associé dans cette table. Les attributs pk et fktable/fkfieldname sont bien entendu mutuellement exclusif.
  • sequence : nom de la séquence à utiliser pour récupérer l'id, dans le cas d'une propriété de type autoincrement (et nécessaire pour certains types de base).

Section déclaration des méthodes

Comme on l'a vu, on peut récupérer des ensembles d'enregistrements soit avec la méthode findAll, soit avec la méthode findBy. Cependant l'inconvénient de la première c'est qu'on récupère tout, sans trie, et que la seconde, elle peut être lente.

On peut déclarer dans le fichier de définition de l'objet DAO, des méthodes supplémentaires pour récupérer des ensembles d'enregistrements. L'avantage est que l'on peut indiquer des critères de sélection (ceux-ci pouvant être dynamiques comme avec findBy), et que c'est aussi rapide que findAll puisque la requête est générée et en dur dans l'objet (Rappelez vous que les classes générées à partir des fichiers de définition sont mis en cache..). On réservera donc l'utilisation de findBy pour des cas où on ne sait pas à l'avance le nombre de critères et/ou leur nature.

Pour déclarer ces nouvelles méthodes, il faut ajouter une section supplémentaire dans le fichier de définition, délimité par la balise <methods>, et contenant un ensemble de balises <method> déclarant chaque méthode.

<?xml version="1.0" ?>
<daodefinition version="1">
...
<methods>
   <method ...>....</method>
   <method ...>....</method>
   ...
</methods>
</daodefinition>

La balise method possède deux attributs, name et type, qui indiquent respectivement le nom de la méthode et son type. Pour l'instant il y a deux types : select pour renvoyer toute la sélection, ou selectfirst pour ne renvoyer que le premier élément de la sélection.

Ensuite cette balise peut contenir 4 balises différentes, qui indique respectivement les paramètres de la méthode, les conditions de sélection (critères), l'ordre de sélection et les limites :

<?xml version="1.0" ?>
<daodefinition version="1">
...
<methods>
   <method name="findByDateAuthor" type="select">

      <parameters>
         <parameter name="" />
         ...
      </parameters>

      <conditions>
         <condition property="" operator="" value="" />
         <condition property="" operator="" value="" />
         ...
      </conditions>

      <order>
         <orderitem property="" way="" />
         ...
      </order>
      <limit offset="" count="" />

   </method>
</methods>
</daodefinition>

Chaque section, parameters, conditions, order, et la balise limit sont facultatives (mais en mettre aucune n'a aucun sens bien sûr puisque cela revient à faire l'équivalent de findAll).

La section parameters

Elle définit les paramètres de la méthodes. Il s'agit simplement d'utiliser une balise parameter pour chaque paramètre, avec un attribut name indiquant le nom du paramètre.

La section conditions

Indique les critères de sélection (correspond à la clause WHERE en sql). La balise conditions permet de regrouper un ensemble de critères (balise condition, sans s). Un attribut, logic permet d'indiquer le "lien" entre les critères : OR ou AND (défaut).

On peut bien sûr déclarer des groupes de critères dans des groupes de critères.

La balise condition quant à elle a trois attributs :

  • property : le nom de la propriété qui servira de critère.
  • value : valeur qui sera comparée avec la propriété. Cela peut être une valeur prédéfinie, ou alors un des paramètres de la méthode. Dans ce cas, il faut mettre le nom du paramètre précédé du caractère $ ;
  • operator : opérateur qui sert de comparaison. Comme on est dans un fichier xml, pour les opérateurs < et >, il faut écrire < et >

La section order

Permet de spécifier dans quel ordre on va récupérer les données. Pour cela, cette section doit contenir une ou plusieurs balises orderitem. Celles-ci ont comme attributs :

  • property : le nom de la propriété sur laquelle le tri s'effectuera ;
  • way : Le sens du tri (asc ou desc ;

Vous aurez compris bien sûr que cela correspond à la clause ORDER BY en SQL.

La balise limit

Permet d'indiquer de ramener qu'un nombre limité d'enregistrements.

  • offset : numéro de l'enregistrement dans la sélection à partir duquel on va récupérer les enregistrements.
  • count : le nombre d'enregistrements que l'on va récupérer ;

Les valeurs peuvent être des nombres, ou alors des noms de paramètres définis dans la méthode (précédé d'un $)

Il ne peut y avoir qu'une balise limit par méthode.

Exemple

<?xml version="1.0" ?>
<daodefinition>
...
<methods>
   <method name="findByDateAuthor" type="select">

      <parameters>
         <parameter name="paramdate" />
         <parameter name="myoffset" />
      </parameters>

      <conditions>
         <condition property="date" operator="<" value="$paramdate" />
         <condition property="author" operator="=" value="Laurent" />
         <conditions logic="or">
            <condition property="valide" operator="=" value="1" />
            <condition property="categorie" operator="=" value="automobile" />
         </conditions>
      </conditions>

      <order>
         <orderitem property="date" way="desc" />
      </order>
      <limit offset="$myoffset" count="15" />
   </method>
</methods>
</daodefinition>

Dans cette exemple, cela va récupérer les enregistrements dont la date est supérieure à la valeur du paramètre $paramdate, ET dont la propriété author est égale à Laurent, ET dont la condition qui suit est respectée : que la propriété valide soit égale à 1 OU que la propriété catégorie soit égale à automobile (ça n'a pas trop de sens mais c'est juste pour l'exemple ;-) ).

On pourra récupérer 15 enregistrements, à partir du nième indiqué dans le paramètre myoffset, et ils seront classés selon la propriété date, par ordre décroissant.

Pour appeler cette méthode en php, il suffira de faire :

// on récupère un objet DAO basé sur un fichier de définition news.daodefinition.xml
// ce fichier map une simple table de news

$DAOnews = CopixDAOFactory::create ('News');

// Récupération des news à partir du huitième enregistrement.
$liste_news =  $DAOnews->findByDateAuthor ('2004-05-24', 8);

Ajouter des méthodes de suppression en xml

À la manière des méthodes de sélection en xml comme on vient de le voir, il est possible de créer des méthodes de suppression : on va pouvoir spécifier les critères de suppression, sans écrire une ligne de code SQL/PHP.

Pour cela, il suffit d'ajouter une balise method, avec dans l'attribut type la valeur delete. Tout comme les méthodes de sélection, vous pouvez définir des paramètres de méthodes, et une section conditions. Par contre, vous ne pouvez pas spécifier une section order et limit, cela n'ayant pas de sens.

<?xml version="1.0" ?>
<daodefinition>
...
<methods>
   <method name="deleteByDate" type="delete">

      <parameters>
         <parameter name="paramdate" />
      </parameters>

      <conditions>
         <condition property="date" operator="<" value="$paramdate" />
      </conditions>
   </method>
</methods>
</daodefinition>
</xml>

Ici on a défini une méthode deleteByDate, qui accepte un paramètre paramdate. Elle supprimera les enregistrements de la table principale de l'objet, dont la propriété date est inférieure au paramètre donné.

Si vous voulez faire des suppressions supplémentaires, dans d'autres tables pour maintenir une cohérence dans vos données, il faudra faire autrement, en créant vos propres méthodes comme nous le verrons ensuite.

Ajouter des méthodes de mise à jour en xml

Le dernier type de méthode que l'on peut déclarer en XML, ce sont les méthodes de mise à jour, c'est à dire qui vont faire des UPDATE en SQL. La différence avec la méthode update générée automatiquement, c'est qu'avec ce type de méthode, vous pouvez mettre à jour seulement un ou quelques champs, et non pas la totalité.

Il faut donc indiquer comme type de methode, update, et au moins une ou plusieurs balises value dans un élément values, comme ceci :

<?xml version="1.0" ?>
<daodefinition>
...
<methods>
   <method name="updateDate" type="update">
      <parameters>
         <parameter name="paramdate" />
      </parameters>

      <values>
         <value property="date" value="$paramdate" />
      </values>
   </method>
</methods>
</daodefinition>

Comme vous le voyez, la balise value accepte deux attributs, property, qui indique la propriété concernée par la mise à jour, et value, contenant la valeur à indiquer dans le champs. Cette valeur peut être une valeur en dur, ou comme ici, la valeur d'un paramètre de la méthode.

Comme pour les méthodes de type delete, vous pouvez également ajouter des conditions.