Programmation objet en bases de données

Eléphanteau du PHP | 35 Messages

01 sept. 2008, 18:26

Bonjour à vous,

Je viens aujourd'hui devant vous car je n'arrive pas à savoir comment utiliser un SGBD relationnel et un script PHP Objet...

Si vous avez des documentations et revue concernant le sujet donnez moi des liens. Cela serait super sympathique de votre part.

Ensuite je vais prendre un exemple d'un petit script de news en gros:
On veut des news avec un titre une date et un texte:
class {
 var $titre;
 var $date;
 var $texte;

//mes méthodes etc.. >Envoie enregistrement affichage

}
Je souhaite savoir si il faut faire quelque chose de spécial pour enregistrer une news ou traiter un formulaire en objet ? j'avoue être perdu ave cla programmation objet en PHP... En java cela ne me pose pas de problème. Donc j'ai bien la philosophie il me faut juste un peu de pratique en PHP objet.

Et comment séparé l'affichage etc.. en faisant du MVC ?

Bon là cela dépasse le sujet j'en suis désolé.

J'attend vos ais et vos idées.

Merci à vous tous pour cette communauté PHP

Mammouth du PHP | 531 Messages

01 sept. 2008, 23:30

J'ai le même problème que toi.
J'ai du mal à comprendre si les opérations sur la base de données ( listing, insert, etc...) doivent être des méthodes de la classe ou non...

Donc je pourrais pas te répondre mais je vais suivre le topic ^^

Modérateur PHPfrance
Modérateur PHPfrance | 6373 Messages

02 sept. 2008, 00:08

J'ai du mal à comprendre si les opérations sur la base de données ( listing, insert, etc...) doivent être des méthodes de la classe ou non...
Généralement c'est séparé : http://fr.wikipedia.org/wiki/Data_Access_Object

Mammouth du PHP | 531 Messages

02 sept. 2008, 00:18

J'ai du mal à comprendre si les opérations sur la base de données ( listing, insert, etc...) doivent être des méthodes de la classe ou non...
Généralement c'est séparé : http://fr.wikipedia.org/wiki/Data_Access_Object
Merci pour le lien.
Donc pour reprendre l'exemple d'Akrogames, en plus de la classe news, on aurait une classe gestionNews par exemple, dans laquelle il y aurait les méthodes de suppression, d'ajout, etc.. ?
Voir même que gestionNews serrait une sous-classe d'une classe générique gestion ?

Modérateur PHPfrance
Modérateur PHPfrance | 6373 Messages

02 sept. 2008, 00:31

Donc pour reprendre l'exemple d'Akrogames, en plus de la classe news, on aurait une classe gestionNews par exemple, dans laquelle il y aurait les méthodes de suppression, d'ajout, etc.. ?
Voir même que gestionNews serrait une sous-classe d'une classe générique gestion ?
Yes, ça parait très bien tout ça

Java ou PHP, ce sont globalement les mêmes concepts qu'on peut mettre en oeuvre.

Mammouth du PHP | 531 Messages

02 sept. 2008, 00:36

J'ai un peu l'impression de m'incruster dans le post mais puisqu'on est dans le vif du sujet et que c'est toujours plus facile à imaginer qu'a faire. Ce début de class serait-il correct ?

Code : Tout sélectionner

class gestionNews { public $id; public $nom; public $contenu; public function __construct( $id, $nom, $contenu ) { } public function getListe() { $req = "SELECT * FROM news"; $res = mysql_query($sql) or die( mysql_error() ); return $res; } }
Ce me parait byzar de faire un return brut du résultat de la requête :roll:

Modérateur PHPfrance
Modérateur PHPfrance | 6373 Messages

02 sept. 2008, 01:14

Ce me parait byzar de faire un return brut du résultat de la requête :roll:
Dans l'article de Wikipédia :
Il est important que cette classe cache complètement d'où viennent les données : elle doit donc renvoyer des objets métier (et non un curseur, un enregistrement, …).
Donc non, c'est pas complet :)

Mammouth du PHP | 531 Messages

02 sept. 2008, 07:21

Donc ça veut dire... un array ? :D

Eléphanteau du PHP | 35 Messages

02 sept. 2008, 09:03

Bonjour à tous,

En ce beau matin de rentré pour nos chers amis étudiant, nous allons reprendre la discution.
En effet c'est exactement le même problème que toi supercanard et tu ne t'incruste pas dans le sujet. Je suis sur que si on réfléchit ensemble on peut comprendre assez vite.
Moi en JAVA je faisait des méthodes pour retourner des résultats et des array avec ODBC...

Enfin si on pouvait nous expliquer un exemple théorique pour que l'on comprenne vraiment comment vous fonctionnez.

J'attend avec impatience votre aide et vos idées.

Thibaud

Mammouth du PHP | 531 Messages

02 sept. 2008, 09:29

Peut être un début de code... :
class gestionPage
{
	public $listePage;
	public function __construct()
	{
		$this->listePage = array();
	}
	public function getListe()
	{
		$req = "SELECT * FROM zen_pages";
		$res = mysql_query( $req ) or die( mysql_error() );
		$i = 0;
		while( $data = mysql_fetch_array( $res ) )
		{
			$listePage[$i]['id'] = $data['id_pages'];
			$listePage[$i]['nom'] = $data['nom'];
			$listePage[$i]['fichier'] = $data['fichier'];
		}
		//print_r($listePage);
		return $listePage;
	}
}
class page {
	public $id;
	public $nom;
	public $fichier;
	public function __construct( $id, $nom, $fichier )
	{
		$this->id = $id;
		$this->nom = $nom;
		$this->fichier = $fichier;
	}
}

$listePage = new gestionPage();
$listePage->getListe();
foreach( $listePage as $v )
{
	echo $v;
}
Biensur tout est faut sur la fin...

Eléphanteau du PHP | 35 Messages

02 sept. 2008, 15:44

J'ai aussi ceci comme exemple:
<?php
class Noyau {
	var $version;
	var $title;

	private function __construct()  {
		$this->$version="0.0.0.1";
		$this->$title="Noyau CMS Eos";
	}

	public function afficheVersion() {
		$noyau = new Noyau();
		return $noyau;
	}
}

$noyau=new Noyau();

echo $noyau->$version;

?>
Pourquoi ce code n'affiche rien... alors que j'ai regarder des tutoriaux ?

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

02 sept. 2008, 16:58

Pour moi, une classe est une définition d'une entité unique qui peut être en relation fonctionnellement avec d'autres classes et qui peut avoir des caractéristiques hérités d'autres classes.

Une classe métier représente une entité dont les propriétés et les méthodes font partie des données et des traitements métiers et donc de la base de données qui représente l'architecture et la mémoire du SI.

Créer des classes métier revient donc à faire une reproduction de la structure d'une base de données relationnelle, à la fois de ses tables, relations, vues et procédures stockées.

La structure d'une table se voit dans une définition de classe dont les propriétés sont les champs de la table et les méthodes sont les vues ou procédures stockées attachées à l'entité (une occurrence type de la table)
Les enregistrements (données) ou occurrences contenus dans une table sont représenté dans le modèle objet par une collection d'objets issus de la même classe représentant une entité.

Par exemple : La structure d'une table "Membre" est la définition de une entité qui lui correspond dans le modèle objet une classe Membre ayant des propriétés et méthodes caractérisant un membre type. Comme ses attributs (nom et prénom) et ses méthodes (set, get, ...)
Par contre, l'ensemble des enregistrement de la table Membre sont représentés par une classe CollectionDeMembres qui définit les caractèristiques de la collection (liste) des membres ainsi que son comportement. Et c'est cette classe qui peut contenir des méthodes de traitement SQL de groupe comme le "Select * From Membre"

Voici un exemple de rapprochement entre une petite base de données relationnelle et un modèle de classes métier.

Base de données : Messagerie

Code : Tout sélectionner

## Tables : Create Table Membre (id int, nom varchar(20), prenom varchar(20), login varchar(20), motDePasse varchar(20)); Create Table Message (id int, contenu text, date datetime, idMembre int); ## Indexes/Realtions : Alter Table Membre Add Constraint PkMembre Primary Key (id); Alter Table Message Add Constraint FkMessageMembre Foreign Key (idMembre) References Membre.id On Update Cascade On Delete NoAction; ## Vues/Procédures stockées : Create View getMembres As Select * From Membre; Create View getMessages As Select * From Message msg Join Membre mbr On msg.idMembre=mbr.id order by date, mbr.id; Create Procedure insertMembre(id, nom, prenom, login, motDePasse) As Insert Into Membre Values (@id, @nom, @prenom, @login, @motDePasse); Create Procedure updateMembre(id, nom, prenom, login, motDePasse) As Update Into Membre Set nom=@nom, prenom=@prenom, login=@login, motDePasse=@motDePasse Where id=@id; Create Procedure deleteMembre(id) As Delete From Membre Where id=@id; Create Procedure selectMembre(id) As Select * From Membre mbr Join Message msg On mbr.id=msg.idMembre Where mbr.id=@id; Create Procedure insertMessage(id, contenu, date, idMembre) As Insert Into Message Values (@id, @contenu, @date, @idMembre); Create Procedure updateMessage(id, contenu, date, idMembre) As Update Message Set contenu=@contenu, date=@date, idMembre=@idMembre Where id=@id; Create Procedure deleteMessage(id) As Delete From Message Where id=@id; Create Procedure selectMessage(id) As Select * From Message msg Join Membre mbr On msg.idMembre=mbr.id Where msg.id=@id order by date; Create Procedure selectMsgMembre(idMembre) As Select * From Message msg Join Membre mbr On msg.idMembre=mbr.id Where mbr.id=@idMembre order by date;
Classes métier :
class Membre {
//
	private $id, $nom, $prenom, $login, $motDePasse;
	public function __construct(){
		//
	}
//
	public function setId($valeur)		{ $this->id 	= $valeur; }
	public function setNom($valeur)		{ $this->nom 	= $valeur; }
	public function setPrenom($valeur)	{ $this->prenom = $valeur; }
	public function setLogin($valeur)	{ $this->login 	= $valeur; }
	public function setMotDePasse($valeur){ $this->motDePasse = $valeur; }
	public function set($id, $nom, $prenom, $login, $motDePasse){ 
		$this->id = $id; $this->nom = $nom; $this->prenom = $prenom; 
		$this->login = $login; $this->motDePasse = $motDePasse;
	}
//
	public function getId()		{ return $this->id; }
	public function getNom()	{ return $this->nom; }
	public function getPrenom()	{ return $this->prenom; }
	public function getLogin()	{ return $this->login; }
	public function getMotDePasse(){ return $this->motDePasse; }
	public function get(){ 
		return array($this->id, $this->nom, $this->prenom, $this->login, $this->motDePasse);
	}
//
	public function getFromDb($id){ 
		try {
      		// On utilise PDO pour se connecter au serveur MySQL
      		$pdo = new PDO('mysql:host=localhost;dbname=Messagerie',
                     'root', '');
      		// Indique à  PDO de lever une exception en cas d'erreur
      		$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
      		// On définit la requête SQL/Vue/Procédure stockée à exécuter.
      		$sql = "Call selectMembre($id)"; //Procédure stockée
      		// On exécute la requête
      		$res = $pdo->query($sql);
      		// On lit le résultat
      		$rows = $res->fetchAll(PDO::FETCH_OBJECT);
			$this->set($rows[0]->id, $rows[0]->nom, $rows[0]->prenom, $rows[0]->login, $rows[0]->motDePasse);
			return $this->get();
   		}
   		catch (PDOException $e) {
      		// On retourne une exception PDO
      		return $e->getMessage();
   		}
	}
	public function addToDb(){ 
		try {
      		// On utilise PDO pour se connecter au serveur MySQL
      		$pdo = new PDO('mysql:host=localhost;dbname=Messagerie',
                     'root', '');
      		// Indique à  PDO de lever une exception en cas d'erreur
      		$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
      		// On définit la requête SQL/Vue/Procédure stockée à exécuter.
      		$sql = "Call insertMembre($this->id, '$this->nom', '$this->prenom', '$this->login', '$this->motDePasse')"; //Procédure stockée
      		// On exécute la requête
      		$res = $pdo->query($sql);
      		return true;
   		}
   		catch (PDOException $e) {
      		// On retourne une exception PDO
      		return $e->getMessage();
   		}
	}
	public function updateDb(){ 
		try {
      		// On utilise PDO pour se connecter au serveur MySQL
      		$pdo = new PDO('mysql:host=localhost;dbname=Messagerie',
                     'root', '');
      		// Indique à  PDO de lever une exception en cas d'erreur
      		$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
      		// On définit la requête SQL/Vue/Procédure stockée à exécuter.
      		$sql = "Call updateMembre($this->id, '$this->nom', '$this->prenom', '$this->login', '$this->motDePasse')"; //Procédure stockée
      		// On exécute la requête
      		$res = $pdo->query($sql);
      		return true;
   		}
   		catch (PDOException $e) {
      		// On retourne une exception PDO
      		return $e->getMessage();
   		}
	}
	public function deleteFromDb(){ 
		try {
      		// On utilise PDO pour se connecter au serveur MySQL
      		$pdo = new PDO('mysql:host=localhost;dbname=Messagerie',
                     'root', '');
      		// Indique à  PDO de lever une exception en cas d'erreur
      		$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
      		// On définit la requête SQL/Vue/Procédure stockée à exécuter.
      		$sql = "Call deleteMembre($this->id)"; //Procédure stockée
      		// On exécute la requête
      		$res = $pdo->query($sql);
      		return true;
   		}
   		catch (PDOException $e) {
      		// On retourne une exception PDO
      		return $e->getMessage();
   		}
	}
}
class CollectionDeMembres {
	private $collection;
	public function __contruct(){
		//
	}
//
	public function set($collection=null){
		$this->collection = $collection;
	}
	public function get($idMembre=null){
		if ($idMembre!=null){
			if ($this->exists($idMembre)) return $this->collection[$idMembre]; 
			else return null;
		}
		else return $this->collection;
	}
	public function getCount(){
		return count($this->collection);
	}
	public function add($membre){
		$this->collection[$membre->id] = $membre;
	}
	public function remove($idMembre){
		unset($this->collection[$idMembre]);
	}
	public function exists($idMembre){
		return isset($this->collection[$idMembre]);
	}

	public function getFromDb(){ 
		try {
      		// On utilise PDO pour se connecter au serveur MySQL
      		$pdo = new PDO('mysql:host=localhost;dbname=Messagerie',
                     'root', '');
      		// Indique à  PDO de lever une exception en cas d'erreur
      		$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
      		// On définit la requête SQL/Vue/Procédure stockée à exécuter.
      		$sql = "Select * From getMembres"; //Vue
      		// On exécute la requête
      		$res = $pdo->query($sql);
      		// On lit le résultat
      		$rows = $res->fetchAll(PDO::FETCH_OBJECT);
			foreach ($rows as $row){
				$membre = new Membre();
				$membre->set($row->id, $row->nom, $row->prenom, $row->login, $row->motDePasse);
				$this->add($membre);
			}
			return $this->get();
   		}
   		catch (PDOException $e) {
      		// On retourne une exception PDO
      		return $e->getMessage();
   		}
	}
} 
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

Eléphanteau du PHP | 35 Messages

02 sept. 2008, 17:16

Merci à toi sadeq !

Bon tu aurais pu faire moins difficile :D mais pour moi j'ai compris donc c'est le principale. Je comprend maintenant ce qu'est une classe métier.

Si j'ai des questions je t'en ferais part.

Bonne fin de journée

Mammouth du PHP | 965 Messages

05 sept. 2008, 11:52

Par contre moi j'ai rien compris :?

Pour la couche métier, on diviser en 2 parties, une classe de gestion avec la base d'un côté et une classe avec des méthodes relative au métier ?

Et pour la couche application on vas mettre les classes pour upload des documents, gérer la connexion a la base de donnée etc... ?

Pour l'instant j'ai fais des classes du type "client" avec dedans tout ce qui doit gèrer l'affichage, les calculs, l'insertion/modification/suppression en base de donnée en une seul classe.

Ensuite une classe pour gérer la connexion a la base et les requêtes. Et une classe pour upload des documents avec retour d'erreur.

Comment faudrait-il structurer tout ça ?

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

05 sept. 2008, 12:33

L'ordre selon le modèle client/serveur à 3 tiers :
  • 1° tiers: Client léger : Interface utilisateur = Affichage/Saisie de données client + événements déclencheurs de la communication avec le 2° tiers (Appels procédures)

    2° tiers: Programme métier : Modules/classes métier représentant les entités, leurs données et leurs méthodes de traitement (modèle objet inspiré du schéma d'une base de données) + déclencheurs de la communication avec le 1° tiers (E/S client) et le 3° tiers (Appels SQL)

    3° tiers: Base de données SQL : SGBD-Base de données-Tables-Requêtes stockées ou directes. + retour de flux vers le 2° tiers (état, erreur, données).
La couche intermédiaire lourde est le programme métier qui joue le rôle du noyau dans la communication Client/Serveur.

Pour expliquer ce que j'ai dis dans mon post précédent, je disais simplement qu'une classe qui normalement représente une entité dans la base de données comme la classe "client" par exemple ne doit avoir une méthode qui fait un "SELECT * FROM client" car la classe est sensée représenter un objet (une instance) physiquement (à l'exécution) or, pour représenter un ensemble de clients il faut créer une liste (tableau ou collection) d'objets (instances) clients.
C'est pourquoi que conceptuellement parlant une classe "collection de client" est justifiée car elle sera réservée à gérer la liste des clients en la remplissant (par un SELECT), en permettant des recherches par exemple, permettre le stockage dynamique dans la ram etc... Elle peut être écrite d'une manière simple en héritant d'objets collections des framework connus.

Voilà pourquoi séparer une entité d'une collection d'entités.
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène