Object-Relational Mapping

Un article de OviWiki.

La librairie LibOrm (Object-Relational Mapping) est une bibliothèque de correspondance entre la base de données et des objets PHP. Elle facilite la définition des tables de données et les requêtes SQL.

Le module LibOrm est disponible sur CVS : [1]

Le chemin complet de la fonctionnalité
LibOrm
Documentation du parent
Pas de parent
Module
LibOrm
version du module
0.6.3


Sommaire

getDescription

Méthode commune à toutes les librairies pour obtenir la description de l'objet partagé.

$instance = bab_functionality::get('LibOrm');

$description = $instance->getDescription();


--> Cette page ne recense pas toutes les possibilités de la librairie. Elle donne un aperçu des fonctions permettant de débuter dans l'utilisation de la librairie.

Exemple

Nous travaillons sur un module d'Ovidentia qui requiert la librairie LibOrm. Pour plus d'explications sur la méthode d'intégration d'une librairie dans un module : Fichiers spécifiques des modules.

Dans notre module, nous gérons 2 tables de données : Contact et AdressePostale. Ces 2 tables sont liées car 1 contact a 1 adresse postale.

Utilisation de la librairie et initialisation

Après installation de la librairie sur le portail, vous pouvez l'utiliser dans votre code PHP en appelant la fonctionnalité. Il est nécessaire d'initialiser le back-end (la base de données) qui sera utilisé. En effet la librairie prévoit des requêtes dans différents formats de base de données : MySQL, XML, RSS...

Cet exemple montre l'utilisation du back-end MySQL. Le constructeur de la classe ORM_MySqlBackend prend en paramètre la variable globale d'Ovidentia (objet babDatabase) :

bab_functionality::get('LibOrm')->initMySql();
$mysqlbackend = new ORM_MySqlBackend($GLOBALS['babDB']);
ORM_MySqlRecordSet::setBackend($mysqlbackend);

Définition des données

Définition de la structure de la table AdressePostale. Il est indispensable de terminer le nom de la classe par Set.

/**
 * Definition of a postal address.
 *
 * @property ORM_PkField        $id
 * @property ORM_TextField      $rue
 * @property ORM_StringField    $codepostal
 * @property ORM_StringField    $ville
 */
class monmodule_AdressePostaleSet extends ORM_MySqlRecordSet {
   function __construct() {
      parent::__construct();
 
     $this->setPrimaryKey('id');
     $this->addFields(
        ORM_TextField('rue')->setDescription('Street'),
        ORM_StringField('codepostal', 10)->setDescription('Zip code'),
        ORM_StringField('ville', 60)->setDescription('City')
     );
   }
}

Définition de la classe AdressePostale en tant qu'enregistrement (record). Lorsque la librairie LibOrm retournera une ligne de la table AdressePostale, la librairie retournera un objet de la classe AdressePostale. Remarque : si vous n'avez pas besoin de personnaliser la classe d'enregistrement, il n'est pas nécessaire de la créer. Elle sera automatiquement créée par la librairie à partir du nom de la classe AdressePostaleSet.

/**
 * A postal address.
 *
 * @property int         $id
 * @property string      $rue
 * @property string      $codepostal
 * @property string      $ville
 */
class monmodule_AdressePostale extends ORM_MySqlRecord {
 
}


Définition de la structure de la table Contact :

/**
 * Definition of a contact.
 *
 * @property ORM_PkField                     $id
 * @property ORM_StringField                 $nom
 * @property ORM_StringField                 $prenom
 * @property ORM_StringField                 $poste
 * @property ORM_StringField                 $bureau
 * @property ORM_StringField                 $telephone
 * @property ORM_StringField                 $fax
 * @property ORM_StringField                 $mobile
 * @property ORM_StringField                 $email
 * @property monmodule_AdressePostaleSet    $adressepostale
 */
class monmodule_ContactSet extends ORM_MySqlRecordSet {
   function __construct() {
      parent::__construct();
 
      $this->setPrimaryKey('id');
      $this->addFields(
         ORM_StringField('nom', 80)->setDescription('Nom'),
         ORM_StringField('prenom', 80)->setDescription('Prénom'),
         ORM_StringField('poste', 50)->setDescription('Métier'),
         ORM_StringField('bureau', 15)->setDescription('Bureau'),
         ORM_StringField('telephone', 30)->setDescription('Téléphone'),
         ORM_StringField('fax', 30)->setDescription('Fax'),
         ORM_StringField('mobile', 30)->setDescription('Téléphone Mobile'),
         ORM_StringField('email', 255)->setDescription('E-mail')
      );
 
      $this->hasOne('adressepostale', 'monmodule_AdressePostaleSet');
   }
}

Définition de la classe Contact en tant qu'enregistrement (record).

/**
 * A contact.
 *
 * @property int                          $id
 * @property string                       $nom
 * @property string                       $prenom
 * @property string                       $poste
 * @property string                       $bureau
 * @property string                       $telephone
 * @property string                       $fax
 * @property string                       $mobile
 * @property string                       $email
 * @property monmodule_AdressePostale    $adressepostale
 */
class monmodule_Contact extends ORM_MySqlRecord {
 
}


Types de champs :

  • ORM_PkField : Primary Key (1 seul par table) - Il faut utiliser la méthode setPrimaryKey pour le créer.
  • ORM_FkField : Foreign key (référence à une autre clé) - Il faut utiliser la méthode hasOne pour les créer.
  • ORM_IntField : entier
  • ORM_BoolField : booléen
  • ORM_CurrencyField : monnaie
  • ORM_DateField : date
  • ORM_TimeField : heure
  • ORM_DatetimeField : date et heure
  • ORM_StringField : chaîne
  • ORM_TextField : chaîne multi-lignes
  • ORM_EnumField : énumération

Requêtes : gestion des données

Nous avons défini nos tables de données dans les chapitres précédents. Pour les exemples de requêtes les définitions de classes doivent être disponibles dans le code PHP.

Insérer des données (équivalent requêtes INSERT dans MySQL)

Pour ajouter une donnée (ici une adresse postale), on définit un nouvel enregistrement en utilisant la méthode newRecord() sur la classe de définition (ici monmodule_AdressePostaleSet).

$adresseset = new monmodule_AdressePostaleSet();
$adresse = $adresseset->newRecord();

Les champs définis dans la classe monmodule_AdressePostaleSet seront accessibles comme des propriétés de la classe monmodule_AdressePostale. La méthode save() sur l'objet effectuera l'enregistrement de la nouvelle donnée.

$adresseset = new monmodule_AdressePostaleSet();
$adresse = $adresseset->newRecord();
 
$adresse->rue = '45, rue Georges André';
$adresse->codepostal = '54000';
$adresse->ville = 'Nancy';
 
$adresse->save();

Remarque :

Dès l'utilisation de la méthode save() sur l'objet, vous travaillez sur la donnée enregistrée. Un nouvel appel à la méthode save() ne créera pas un nouvel enregistrement mais modifiera la donnée en cours :

$adresseset = new monmodule_AdressePostaleSet();
$adresse = $adresseset->newRecord();
 
$adresse->rue = '45, rue Georges André';
$adresse->codepostal = '54000';
$adresse->ville = 'Nancy';
 
$adresse->save();
 
$adresse->codepostal = '78000';
$adresse->ville = 'Versailles';
 
$adresse->save();

Gestion des données liées

Nos définitions de tables prévoyaient une liaison entre un contact et une adresse postale. Voici un exemple permettant d'insérer un contact et son adresse automatiquement. Il est nécessaire pour cela de définir une liaison JOIN :

$contactset = new monmodule_ContactSet();
$contactset->join('adressepostale');
 
$contact = $contactset->newRecord();
 
$contact->nom = 'Martin';
$contact->prenom = 'Henry';
$contact->adressepostale->rue = '45, rue Georges André';
$contact->adressepostale->codepostal = '54000';
$contact->adressepostale->ville = 'Nancy';
 
$contact->save();

Sélectionner des données (équivalent requêtes SELECT en MySQL)

La sélection de données s'effectue par la méthode select() sur l'objet de définition. Il est conseillé d'utiliser la commande foreach pour parcourir les résultats.

Cet exemple montre la sélection de tous les contacts et affiche leurs noms.

$contactset = new monmodule_ContactSet();
 
$contacts = $contactset->select();
foreach ($contacts as $contact) {
    echo $contact->nom;
}

Cet exemple montre la sélection de tous les contacts dont le prénom est Paul et affiche leurs noms. On passe en paramètre à la méthode select() un critère (objet ORM_Criteria).

$contactset = new monmodule_ContactSet();
 
$contacts = $contactset->select($contactset->prenom->is('Paul'));
foreach ($contacts as $contact) {
    echo $contact->nom;
}

Cet exemple montre la sélection de tous les contacts dont le prénom est Paul et dont le nom commence par André et affiche leurs noms. L'opérateur _AND_ permet la création d'un critère à partir de 2 critères.

$contactset = new monmodule_ContactSet();
$contactset->join('adressepostale');
 
$contacts = $contactset->select($contactset->prenom->is('Paul')->_AND_($contactset->nom->startsWith('André')));
foreach ($contacts as $contact) {
    echo $contact->nom;
}

Une autre méthode pour sélectionner un enregistrement :

Pour sélectionner un seul enregistrement de table, vous pouvez utiliser la méthode select() mais choisissez plutôt la méthode get(). Cette dernière retourne exclusivement l'objet en recevant la valeur de la clé primaire.

$contactset = new monmodule_ContactSet();
$contactset->join('adressepostale');
 
$contact = $contactset->get(5);
if ($contact !== NULL) {
    echo $contact->nom;
}

Types de critères :

  • greaterThan
  • greaterThanOrEqual
  • lessThan
  • lessThanOrEqual
  • in
  • is
  • isNot
  • notIn
  • notLike
  • like
  • startsWith
  • endsWith
  • contains
  • matchOne
  • matchAll
  • matchAllWords
  • likeOne
  • likeAll
  • fieldIsNull

Opérateurs :

  • _AND_
  • _OR_
  • _NOT_ : un critère supplémentaire doit être passé en paramètre
  • _NOT : permet d'inverser un critère (aucun critère ne doit être passé en paramètre)

Ordonner les résultats :

Vous pouvez ordonner simplement les résultats en utilisant la méthode orderAsc() ou orderDesc() de cette manière :

$contactset = new monmodule_ContactSet();
$contactset->join('adressepostale');
 
$contacts = $contactset->select()->orderAsc($contactset->nom);
foreach ($contacts as $contact) {
    echo $contact->nom;
}

Mettre à jour des données (équivalent requêtes UPDATE en MySQL)

La modification d'une donnée passe par la méthode save() sur l'objet en cours. La donnée en cours peut provenir d'une requête de sélection ou de création.

Cet exemple montre 2 appels à la méthode save(). Le premier appel créé un nouvel enregistrement. Le deuxième effectue une modification de l'enregistrement.

$adresseset = new monmodule_AdressePostaleSet();
$adresse = $adresseset->newRecord(); 
$adresse->rue = '45, rue Georges André';
$adresse->codepostal = '54000';
$adresse->ville = 'Nancy';
 
$adresse->save();
 
$adresse->codepostal = '78000';
$adresse->ville = 'Versailles';
 
$adresse->save();

Cet exemple montre l'appel à la méthode save() après une requête de sélection. Le code affecte une majuscule au prénom Paul à tous les contacts qui n'en n'avaient pas.

$contactset = new monmodule_ContactSet();
$contactset->join('adressepostale');
 
$contacts = $contactset->select($contactset->prenom->is('paul'));
foreach ($contacts as $contact) {
    $contact->prenom = 'Paul';
    $contact->save();
}

Supprimer des données (équivalent requêtes DELETE en MySQL)

Pour supprimer des données, on utilise la méthode delete sur l'objet de définition. Cette méthode prend en paramètre un critère (objet ORM_Criteria).

Dans cet exemple, on supprime tous les contacts dont le prénom est paul :

$contactset = new monmodule_ContactSet();
 
$contacts = $contactset->delete($contactset->prenom->is('paul'));


Méthodes spécifiques au backend mysql

$record->getValues()

Permet d'obtenir les valeurs d'un record sous la forme d'un tableau associatif, les données des records liés sont inclus comme des sous-tableaux

$record->setValues($associativeArray)

Permet de définir les valeurs d'un record en utilisant un tableau associatif, les données des records liés peuvent être définis en utilisant des sous-tableaux.

$record->getOutputValues()

Permet d'obtenir les valeurs d'un record sous la forme d'un tableau associatif, les valeurs sont obtenues en utilisant la méthode output() de chaque objet ORM_Field du ORM_RecordSet associé.

le tableau peut être utilisé pour afficher les données

$record->getFormOutputValues()

Permet d'obtenir les valeurs d'un record sous la forme d'un tableau associatif, les valeurs sont obtenu en utilisant la méthode formOutput() de chaque objet field du set associé.

Le tableau peut être utilisé pour remplir un formulaire de saisie

$record->setFormInputValues($associativeArray)

Comme setValues, permet de définir les valeurs d'un record en utilisant un tableau associatif. Cependant les valeurs sont obtenues en utilisant la méthode input() de chaque objet field du set associé.

Cette méthode est généralement à utiliser lorsque le tableau $associativeArray provient d'un formulaire de saisie.