Le blog du pangolin

Accueil > Programmation > PHP > CodeIgniter > Un ORM simplissime pour CodeIgniter : datamapper

Un ORM simplissime pour CodeIgniter : datamapper

vendredi 11 novembre 2011, par Super Pangolin

Cet ORM est compatible toutes versions de codeIgniter jusqu’à la 2.0.2. Pour la 2.0.3, je vous fournirai une astuce toute crade pas belle mais qui fonctionne. Développé par wanwizard, il est disponible sur leur site ou par sparks.

Installation

Pour ceux qui voudraient l’installer par sparks, la ligne de commande est fournie ici : http://getsparks.org/packages/DataMapper-ORM/versions/HEAD/show
Pour les autres :
Téléchargez la dernière version et copiez les répertoires config, datamappre, helpers, languages libraries et models dans le répertoire application de votre codeIgniter.
Editez le fichier config/datamapper.php et configurez le pour votre environnement (en dev, rien à changer).
En l’état actuel, on ne peut normalement pas utiliser datamapper avec codeigniter 2.0.3 car il a besoin d’accéder aux méthodes de l’objet active records, qui sont désormais « protected ». La méthode la plus simple (mais crade, mais qui marche) si vous ne voulez pas rester coincé à la version 2.0.2 est de modifier la définition de la classe datamapper en ajoutant « extends CI_DB » :

class DataMapper  extends CI_DB implements IteratorAggregate {

Je ne sais pas exactement quelles sont les conséquences en terme de sécurité, performance et utilisation mémoire, donc à éviter en production.

Exemple de base :
Créez un modèle avec le contenu suivant :

<?php
class modeleArticles extends DataMapper{
        var $table='spip3_articles';
}

en remplaçant ’spip3_articles’ par le nom d’une table de votre base.
Ensuite, il suffit de l’appeler dans un contrôleur :

<?php
class testDatamapper extends CI_Controller{
        function __construct(){
                parent::__construct();
        }
       
        function index(){
                $this->load->database('pangolin');
                $this->load->spark('DataMapper-ORM/1.8.1');
                $modeleArticles = new modeleArticles();
               
                $modeleArticles->limit(5)->get();
                echo "<pre>";
                var_dump($modeleArticles);
                echo "</pre>";
               
                echo "<ul>";
                foreach($modeleArticles as $monArticle){
                        echo "<li>", $monArticle->titre, "</li>";
                }
                echo "</ul>";
        }
}

Voici ce que ça donnerait avec juste active records :

        function noDM(){

                $this->load->database('pangolin');
                $this->db->limit(5);
                $res = $this->db->get('spip3_articles');
                $tArticles = $res->result();
                echo "<pre>";
                var_dump($tArticles);
                echo "</pre>";
               
                echo "<ul>";
                foreach($tArticles as $monArticle){
                        echo "<li>", $monArticle->titre, "</li>";
                }
                echo "</ul>";

        }

Rien de bien différent, donc. Alors quel est l’intérêt de datamapper ? De toute évidence pas dans un exemple aussi simple. Comme tout ORM, il gère les relations entre les tables et facilite la mise à jour des données.

Contrainte : Le nom de la colonne contenant la clé primaire doit OBLIGATOIREMENT être ’id’ EN MINUSCULE (je me suis déjà fait avoir...), ce qui, en soit, n’est pas vraiment gênant, mais pour ma part, je préfère préfixer les noms de colonne avec des trigrammes rappelant le nom de la table.
Autre contrainte : les clés externes doivent être de la forme _id

Astuces sur les modeles
On peut définir les attributs « created_field » et « updated_field » qui vont contenir les noms des champs stockant les timestamp de création et de modification d’un enregistrement.
Exemple :

class monModeleDatamapper extends DataMapper {

   var $created_field = 'date_creation';
   var $updated_field = 'date_mise_a_jour';

   function __construct($id = NULL)
   {
       parent::__construct($id);
   }
}

Petit exemple pas original avec trois petites tables : une gestion de cd.

Construisons les tables cds, cds_artistes, cds_styles :

-- --------------------------------------------------------

--
-- Structure de la table `cds`
--

CREATE TABLE IF NOT EXISTS `cds` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `cd_titre` varchar(100) COLLATE latin1_general_ci DEFAULT NULL,
 `cds_artiste_id` bigint(20) NOT NULL,
 `cds_style_id` bigint(20) DEFAULT NULL,
 PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci AUTO_INCREMENT=1 ;

-- --------------------------------------------------------

--
-- Structure de la table `cds_artistes`
--

CREATE TABLE IF NOT EXISTS `cds_artistes` (
 `id` bigint(20) NOT NULL AUTO_INCREMENT,
 `art_nom` varchar(100) NOT NULL,
 PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

-- --------------------------------------------------------

--
-- Structure de la table `cds_styless`
--

CREATE TABLE IF NOT EXISTS `cds_styless` (
 `id` bigint(20) NOT NULL AUTO_INCREMENT,
 `stl_libelle` varchar(50) NOT NULL,
 PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

On définit des modèles minimalistes :

Pour la table cds (cd.php) :

<?php
class cd extends DataMapper{
        var $has_one = array('cds_style', 'cds_artiste');
}

Pour la table cds_styles (cds_style.php) :

<?php
class cds_style extends DataMapper{
        var $has_many = array("cd");
}

Pour la table cds_artistes (cds_artiste.php) :

<?php
class cds_artiste extends DataMapper{
        var $has_many = array("cd");
}

Insérons quelques enregistrements :

                $this->load->database('pangolin');
                $this->load->spark('DataMapper-ORM/1.8.1');
               
                $cdStyle = new cds_style;
                $cdStyle->stl_libelle = 'Rock';
                $cdStyle->save();
                $cdStyle = new cds_style;
                $cdStyle->stl_libelle = 'Jazz';
                $cdStyle->save();
                $cdStyle = new cds_style;
                $cdStyle->stl_libelle = 'Blues';
                $cdStyle->save();
               
                $cdArtiste = new cds_artiste;
                $cdArtiste->art_nom = 'Pink Floyd';
                $cdArtiste->save();
                $cdArtiste = new cds_artiste;
                $cdArtiste->art_nom = 'Eric Clapton';
                $cdArtiste->save();
                $cdArtiste = new cds_artiste;
                $cdArtiste->art_nom = 'The Beatles';
                $cdArtiste->save();
               
                $monCD = new cd;
                $monCD->cd_titre = 'The Dark Side of the Moon';
                $monCD->cds_artiste_id = 1;
                $monCD->cds_style_id = 1;
                $monCD->save();

                $monCD = new cd;
                $monCD->cd_titre = 'Crossroads';
                $monCD->cds_artiste_id = 2;
                $monCD->cds_style_id = 3;
                $monCD->save();

                $monCD = new cd;
                $monCD->cd_titre = 'Abbey road';
                $monCD->cds_artiste_id = 3;
                $monCD->cds_style_id = 1;
                $monCD->save();

Pour afficher ces données, rien de plus simple : c’est datamapper qui gère les relations.

                $this->load->database('pangolin');
                $this->load->spark('DataMapper-ORM/1.8.1');
                $listeCD = new cd;
                $listeCD->get();
                foreach($listeCD as $monCD){
                        echo $monCD->cd_titre, ', ';
                        echo $monCD->cds_artiste->get()->art_nom, ' (';
                        echo $monCD->cds_style->get()->stl_libelle, ')<br />';
                }

Petites précisions sur ce code :
$monCD->cds_artiste contient un objet de type cds_artiste avec toutes ses données à null.
$monCD->cds_artiste->get() permet de l’initialiser avec les données correspondant à l’id stocké dans la colonne cds_artiste_id.
Résultat :

The Dark Side of the Moon, Pink Floyd (Rock)
Crossroads, Eric Clapton (Blues)
Abbey road, The Beatles (Rock)

C’est tout. A vous de jouer !!


La nouvelle version (1.8.2) est compatible CI 203 mais en modifiant le fichier inde.php de CI.

Un message, un commentaire ?

Qui êtes-vous ?
Votre message

Pour créer des paragraphes, laissez simplement des lignes vides.