IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

PhpMyObject manuel

Date de publication : 29/07/2007 , Date de mise à jour : 25/03/2008

Par Nicolas BOITEUX
 

PMO est une API développée en PHP. Un Object relational Mapping (ORM) qui transforme les résultats de requêtes SQL en objets. PMO est basé en parti sur le motif de conception Active record. PMO gère les relations 1:1, 1:n, n:m.

I. Introduction
II. Pourquoi utiliser PMO ?
III. Fonctionnement global
IV. Le controlleur PMO_MyController
V. Les objets PMO_MyObject
VI. Les objets PMO_MyTable
VI. Les maps PMO_MyMap
VIII. Le class loader
IX. L'objet PMO_MyDbms
X. L'objet Collector
XI. L'objet PMO_MyConfig
XII. Les Exceptions
XIII. Exemples
XIV. Exemple de controleurs


I. Introduction

Source wikipedia: "En génie logiciel, le patron de conception (design pattern) active record est une approche pour lire les données d'une base de données. Les attributs d'une table ou d'une vue sont encapsulés dans une classe. Ainsi l'objet, instance de la classe, est lié à un tuple de la base. Après l'instanciation d'un objet, un nouveau tuple est ajouté à la base au moment de l'enregistrement. Chaque objet récupère ses données depuis la base; quand un objet est mis à jour, le tuple auquel il est lié l'est aussi. La classe implémente des accesseurs pour chaque attribut."

Ce manuel décrit la version 0.14. Il va vous apprendre à utiliser PMO et à développer plus simplement et plus rapidement vos applications PHP.


II. Pourquoi utiliser PMO ?

Voici les raisons pour lesquelles PMO est succeptible de vous intérresser:

  • vous faites de l'orienté objet
  • vous voulez encapsuler la gestion des données dans des classes dédiées à cela
Voici les raisons pour lesquelles PMO est succeptible de vous intérresser:

  • il est simple
  • il permet d'utiliser du SQL
  • il découvre automatiquement les schémas de la base (pas de fichiers XML), et utilise la persistance
  • il utilise des interfaces
  • il est conçu à partir d'une architecture logiciel (UML)
  • il permet d'utiliser vos propres classes

III. Fonctionnement global

PMO s'utilise entre le SGBD et l'application.

PMO interroge le SGBD et traite le résultat de la façon suivante:

Il transforme chaque ligne résultat de la requête SQL en objets.
exemple avec une table utilisateur contenant 10 utilisateurs

			SELECT * from utilisateur;

			va renvoyer 10 PMO_MyObject utilisateur.
			
exemple avec une table utilisateur contenant 10 utilisateurs, une table ville contenant 5 villes

			SELECT * from utilisateur,ville WHERE utilisateur.id_ville=ville.id_ville;

			va renvoyer 10 PMO_MyObject utilisateur, et 5 PMO_MyObject ville
			

IV. Le controlleur PMO_MyController

L'objet PMO_MyController sert à executer une requête SQL.

L'objet PMO_MyController renvoit une map remplie d'objets contenant les données.
Executer une requête SQL

			$controller = New PMO_MyController();

			$map = $controller->query("SELECT * FROM utilisateur,ville ; ");
			while($result = $map->fetch()){
				echo $result['ville']->nom;
				echo $result['utilisateur']->nom;
			}
			
Une vue haut niveau des interractions du controlleur avec les autres objets de PMO, ainsi qu'avec un controlleur d'une autre application


V. Les objets PMO_MyObject

PMO crée des objets de type PMO_MyObject pour stocker les données.

PMO_MyObject possède trois propriétés:

  • object_id : identifiant unique de l'objet
  • object_table : une référence qui pointe vers un objet PMO_MyTable décrivant le schéma de la table dont découle l'objet
  • object_attribute : un tableau indexé contenant vos données, nom de colonne => valeur
PMO_MyObject possède plusieurs méthodes:

  • ::factory(nomdetable) : sert à créer un objet PMO_MyObject vide conforme au schéma de la table pour insertion
  • ::override(nomdetable) : sert à créer un objet PMO_MyObject vide conforme au schéma de la table pour update (par défaut tout les attributs sont NULL - !attention aux pertes de données si vous faites un save() !)
  • load() : charge un objet depuis la base de données (les champs équivalents à la clef primaire doivent être renseignés)
  • delete() : supprimer l'objet de la base de données ce qui correspond à 1 ligne dans une table
  • save() : écrire ou mettre à jour l'objet de la base de donnée ce qui correspond à 1 ligne dans une table
  • toXml() : renvoit l'objet sous la forme d'un fichier XML
  • getTable() : renvoit la référence de l'objet PMO_MyTable duquel il découle.
  • getRelated() : renvoit une map contenant tous les objets liés 1:n à cet objet.
Afficher la valeur de l'attribut

			echo $objet->attribut;

			exemple:
			echo $utilisateur->login;
			
Modifier la valeur de l'attribut

			$objet->attribut = $valeur;

			Exemple:
			$utilisateur->login = "newlogin";
			
Charger un objet depuis la BDD

			$objet->load();

			Exemple pour l'utilisateur 1:

			/** creation d'un objet équivalent à la table utilisateur */
			$utilisateur = PMO_MyObject::factory('utilisateur');

			/** user_id correspond à la clef primaire*/
			$utilisateur->user_id = 1;

			$utilisateur->load();
			
Enregistrer un objet en BDD

			$objet->save();

			exemple:
			$utilisateur->save();
			
Supprimer un objet de la BDD

			$objet->delete();
			
			exemple:
			$utilisateur->delete();
			
Récupérer un objet au format XML

			$objet->toXml($encoding);
			
			exemple:
			$utilisateur->toXml("ISO-8859-1");
			

VI. Les objets PMO_MyTable

PMO crée des objets persistants. Un objet PMO_MyTable décrit le schéma d'une table de la base de donnée.

  • table_name : nom de la table
  • table_pk : array contenant le nom de toutes les clefs primaires
  • table_attribute : un tableau indexé d'attributs contenant le nom de la colonne / Null/ type / default / extra => valeur
Les méthodes de PMO_MyTable:

  • getTablename : récupérer le nom de la table
  • getAutoincrement : récupérer le nom du champ autoincrement
  • getPk : récupérer le nom des clefs primaires
  • setPerm : parametrer un champs en read / write
  • getReverseAlias : récupérer le nom d'une colonne à partir de son alias
  • toCache : reécrire la classe persistante
  • getClassname : nom de la classe fille étendant PMO_MyObject
Retrouver l'objet table lié à un objet PMO_MyObject

			$objetable = $objet->getTable()
			
			exemple:
			$tableutilisateur = $utilisateur->getTable();
			
Modifier le mappage du nom d'une colonne

			Editez la variable table_alias du cache de la table
			
			exemple pour que customer_id devienne toto:
				protected $table_alias = Array(
				'customer_id'=> 'toto'
				);
			
Il est possible d'utiliser ses propres objets et de les associer à un table (voir aussi class loader).
Associer un objet à une table

			Editez la variable table_classname du cache de la table
			
			exemple:
			protected $table_classname = "newclassname";
			
Les classes persistantes PMO_MyTable sont écrites par PMO à la première execution de votre script dans le répertoire PMO_Core/PMO_MyTable/


VI. Les maps PMO_MyMap

PMO référence les objets PMO_MyObject dans une structure de type PMO_MyMap.
Représentation de la structure de la propriété PMO_MyMap

			PMO_MyMap -|
				   |-- row --|
							|--> référence PMO_MyObject
				   
			
Exemple avec une table utilisateur et ville


			SELECT * from utilisateur,ville WHERE utilisateur.id_ville=ville.id_ville; 
			
			qui renverait deux lignes serait représenté comme ça:
			
			PMO_MyMap -|
						|-- row  0 --|
				                     |--> référence PMO_MyObject utilisateur
   				                     |--> référence PMO_MyObject ville
						|-- row  1 --|
				                     |--> référence PMO_MyObject utilisateur
   				                     |--> référence PMO_MyObject ville
				   
			
Chaque Row permet d'identifier les relations entre les objets. Ainsi on sait que les objets du row 0 sont liés ensemble.

PMO_MyMap contient une propriété : un array indexé

Les méthodes de PMO_MyMap:

  • getObjectByValue(nom de la table de l'objet, nom de l'attribut, valeur de l'attribut): permet de retrouver un objet dans la map grace à la valeur d'un de ses attributs.
  • getMapByTable(nom de la table): permet de renvoyer une nouvelle sous map MyMap qui ne contient que des objets de la table passé en paramètre. C'est une forme de filtre.
  • getMapByValue(nom de la table de l'objet, nom de l'attribut, valeur de l'attribut): permet de renvoyer une nouvelle map qui ne contient que les lignes de résultats contenant l'objet que l'on passe en paramètre.
  • count(): retourne le nombre de row dans la map
  • fetch(): retourne un row de la map
Récupérer ligne par ligne la map

			$result = $map->fetch();
			
			exemple:
			while($result = $map->fetch()){
				echo($result['utilisateur']->login);
			}
			
Créer une map ne contenant que des objets relatifs à un objet PMO_MyObject

			$newmap = $map->getMapRelated($PMO_object);
			
			exemple:
			$film->titre = 'tarzan';
			$newmap = $map-> getMapRelated($film);
			while ($result = $newmap->fetch()){
				echo $result['salle']->numero;
				echo $result['cinema']->nom;
			}
			
Créer une map ne contenant que des objets relatifs à un objet dont ses n primary key ont ces valeurs

			$newmap = $map->getMapByObjectByValue($PMO_MyObject);
			
			exemple:
			$user->user_id = 1;
			$user->user_departement_id = 1;
			$newmap = $map->getMapByObjectByValue($user);
			
Retrouver un objet

			$object = $map->getObjectByValue("nomdetable", "nomdecolonne", "valeur");

			exemple:
			$object = $map->getObjectByValue("utilisateur", "login", "toto");
			
Créer une autre map ne contenant que des objets provenant d'une table x

			$newmap = $map->getMapByTable("nomdelatable")

			exemple:
			$newmap = $oldmap->getMapByTable("utilisateur");
			
Créer une map ne contenant que des objets relatifs à un objet dont la colonne x à cette valeur

			$newmap = $map->getMapByValue("nomdetable", "nomdecolonne", "valeur");
			
			exemple:
			$newmap = $oldmap->getMapByValue("utilisateur", "login", "toto");
			

VIII. Le class loader

Le class loader permet d'utiliser vos propres objets héritant de PMO_MyObject, pour cela vous devez créer une class dans le répertoire class_loader/. Le nom du fichier doit être class_xxxxx.php
exemple de class utilisateur implémentant une méthode helloworld()

			class utilisateur extends PMO_MyObject{
				public function helloworld(){
					echo('this class is instanciate when a database table user exist');
				}
			}
		
Il faut ensuite éditer la classe PMO_MyTable_xxx.php se trouvant par défaut dans le répertoire PMO_Core/PMO_MyTable/ qui décrit la structure de votre table. Cette classe est crée automatiquement par PMO dans ce répertoire.
exemple de modification de PMO_MyTable_xxx.php

			Editez cette ligne:
			protected $table_classname = "utilisateur";
		
Par défaut $table_classname vaut NULL ce qui signifie que vous utilisez pour toutes vos tables, l'objet générique PMO_MyObject
appel de la méthode helloword
			
			L'objet peut être ensuite utilisé de cette façon:
			$object = PMO_MyObject::factory('utilisateur');
			$object->helloworld();		
		

IX. L'objet PMO_MyDbms

L'objet PMO_MyDbms implémente les différents drivers pour accéder à la base de donnée.

PMO_MyDbms implémente le design pattern singleton.

PMO_MyDbms permet :

  • d'encapsuler un lien mysql, ou un objet PDO
  • d'executer des requetes SQL
  • d'utiliser le transactionnel avec PDO
  • de récupérer des descriptions de table
  • de récupérer la valeur d'un champs autoincrement
  • de loguer les requêtes SQL
Les méthodes de PMO_MyDbms

  • factory(): instancie un objet PMO_MyDbms, ou renvoie la référence de l'objet s'il existe déjà
  • beginTransaction(): commence une transaction (PDO)
  • commit(): commit tous les PMO_MyObject qui ont été save() (PDO)
  • rollback(): rollback tous les PMO_MyObject qui ont été save() (PDO)
  • getLog(): récupère les logs sous forme de array
exemple d utilisation des transactions avec PDO

			PMO_Dbms::factory()->beginTransaction();
			
			$object->save();
			
			PMO_Dbms::factory()->commit();
			

X. L'objet Collector

PMO permet d'utiliser les fonctions SQL dans les requêtes SQL, et stocke les résultats dans un objet PMO_MyObject dédié du nom de collector
Représentation de la structure de la propriété PMO_MyMap avec le collector

			PMO_MyMap -|
				   |-- row --|
							|--> référence PMO_MyObject Collector
							|--> référence PMO_MyObject
				   
			
Exemple avec une table utilisateur et ville


			SELECT count(id_utilisateur),nom_utilisateur,count(id_ville),nom_ville from utilisateur,ville WHERE utilisateur.id_ville=ville.id_ville; 
			
			qui renverait deux lignes serait représenté comme ça:
			
			PMO_MyMap -|
						|-- row  0 --|
				                     |--> référence PMO_MyObject collector
				                     |--> référence PMO_MyObject utilisateur
   				                     |--> référence PMO_MyObject ville
						|-- row  1 --|
				                     |--> référence PMO_MyObject collector
				                     |--> référence PMO_MyObject utilisateur
   				                     |--> référence PMO_MyObject ville
				   
			
exemple d utilisation du collector

			require_once("core/PMO_MyController.php");
			
			$controler = new PMO_MyController();
			$map = $controler->query("SELECT count(id),nom FROM employe ;");
			
			$result = $map->fetch();
			echo($result['collector']->get('count(id)');
			

XI. L'objet PMO_MyConfig

La classe PMO_MyConfig sert à centraliser les configurations de toutes les autres classes. Elle implémente le design pattern singleton.

Les méthodes de PMO_MyConfig

  • factory: crée ou renvoit la référence de l'objet PMO_MyConfig existant
  • set: définit la valeur d'un paramêtre
  • get: récupère la valeur d'un paramêtre
  • show: liste tous les paramêtres et leurs valeurs
exemple d utilisation de PMO_MyConfig

			$config = PMO_MyConfig::factory();
			$config->set('PMO_MyDbms.DRIVER','mysql');
			$config->set('PMO_MyDbms.HOST','localhost');
			$config->set('PMO_MyDbms.USER','pmo');
			$config->set('PMO_MyDbms.PASS','pmo');
			$config->set('PMO_MyDbms.BASE','sakila');						
			

XII. Les Exceptions

Pmo permet d'utiliser les exceptions pour les opérations sur les objets.
exemple de gestion exception

			try{
				$object->save()
			}catch(Exception $e){
				die($e->getMessage());
			}
			
exemple de gestion exception

			try{
				$user->loginz = "toto";
			}catch(Exception $e){
				die($e->getMessage());
			}
			

XIII. Exemples

Pour les exemples, j'utiliserais une table employe, mais ça fonctionne pareil avec n'importe laquelle de vos tables

Dézippez l'archive de PhpMyObject, et configurez le fichier yourconfig.php pour que PMO puisse intérroger votre base de donnée.

Affichage du nom des 20 premiers employés de la table employe.

			require_once("core/PMO_MyController.php");
			
			$controler = new PMO_MyController();
			$map = $controler->query("SELECT * FROM employe limit 20 ;");
			
			while ($result = $map->fetch()){
				echo($result['employe']->nom);
			}
		
Affichage du nom des 20 premiers employés de la table employe et du numéro de leur place de parking.

			require_once("core/PMO_MyController.php");
			
			$controler = new PMO_MyController();
			$map = $controler->query("SELECT * FROM employe,parking WHERE employe.id_employe=parking.id_employe limit 20 ;");
			
			while ($result = $map->fetch()){
				echo($result['employe']->nom);
				echo($result['parking']->numero_place);
			}
		
Modification du nom de l'employe dupont en durand

			require_once("core/PMO_MyController.php");
			
			$controler = new PMO_MyController();
			$map = $controler->query("SELECT * FROM employe ;");
			
			$employe = $map->getObjectByValue("employe", "nom", "dupont");
			$employe->nom = "durand";
			$employe->save();
		
Autre exemple si vous connaissez déjà toutes les informations de Durand, il est inutile d'utiliser le controller. Attention aux pertes de données, override() initialise à NULL toutes les colonnes qui n'ont pas été renseignées.

			require_once("core/PMO_MyController.php");
			
			$employe = PMO_MyObject::override("employe");
			$employe->id = "250";
			$employe->nom = "durand";
			$employe->save();
		
Création d'un objet employe qui a pour nom de Masson

			require_once("core/PMO_MyController.php");
			
			$employe = PMO_MyObject::factory("employe");
			$employe->nom = "Masson";
			$employe->save();
		
Affichage de tous les noms d'un film dans lequel a joué un acteur Dupont. Pour l'exemple, nous ne préciserons pas ce critère directement dans la requête SQL, mais nous utiliserons les relations PMO entre objets.

			require_once("core/PMO_MyController.php");
			
			$controler = new PMO_MyController();
			$map = $controler->query("SELECT * FROM film,actor WHERE film.actor_id=actor.actor_id ;");
			
			$actor = $map->getObjectByValue("actor", "nom", "dupont");
			
			// nous récupérons la map de film lié à l'acteur sélectionné ci-dessus			
			$mapoffilm = $actor->getRelated('film');

			while ($result = $mapoffilm->fetch()){
				echo($result['film']->nom_film);
			}

		

XIV. Exemple de controleurs

exemple d'un controleur développé avec PMO
			
			require_once("core/PMO_MyController.php");
						
			class gestionutilisateur(){
					
					/** récupère un utilisateur dans SGBD */
					public function getUser(PMO_MyObject $user){
						/** charge les données à partir du sgbd */
						$user->load();
						
						/** retourne l'objet user */
						return $user;
					}
						
					/** ajoute un utilisateur en base */
					public addUser(PMO_MyObject $user){
						/** ecrit les données de l'objet dans la table utilisateur */
						$user->save();
					}
					
					
					/** creer un objet utilisateur */
					public createUser(){
						return PMO_MyObject::factory("utilisateur");
					}
					
					/** supprime un utilisateur */
					public removeUser(PMO_Object $user){
						/** supprime les données relative à l'objet dans la table utilisateur */
						$user->delete();
					}

					/** affiche les données utilisateurs */
					public printUser(PMO_Object $user){
						echo($user->user_id);
						echo($user->name);
						echo($user->login);
					}
			
					/** controle le mot de passe de l'utilisateur */
					public checkPass(PMO_Object $user, $password){
						if($user->pass == sha1($password))
							return TRUE;
							
						return FALSE;
					}		
			}
			
exemple d'un code impératif utilisant PMO
			
			require_once("core/PMO_MyController.php");		
			
			/** instancie le controlleur */
			$controler = new PMO_MyController();

			/** cree une map d'objets */
			$map = $controler->query("SELECT * FROM user,ville where user_id="$userid
			AND ville.id_ville=user.id_ville; ");
			
			while ($result = $map->fetchMap()){
				$utilisateur = $result['user'];
				$ville = $result['ville'];
				
				echo("Nom:".$utilisateur->nom);
				echo("Ville:"$ville->nom_ville);
			}		
			


Valid XHTML 1.1!Valid CSS!

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 29/07/2007 Nicolas BOITEUX. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.