Le modèle objet de PHP

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

14 févr. 2005, 17:07

Le modèle objet de PHP a pris son chemin avec PHP5.

On peut en profiter pour changer de paradigme de programmation PHP.

En effet, la page PHP peut être conçue comme un objet et ainsi éviter la programmation linéaire quon retrouve dans la majorité des codes d'aujourd'hui.
Cette méthode adoptée aujourd'hui est devenue un classique bavare. PHP en souffre, puisque la programmation linéaire ou procédurale présente l'incenvénient majeur de non lisibilité = non spécialisétion du code = difficulté de maintanance.

En effet, PHP est souvent confondu avec HTML puisque les deux cohabitent parfaitement dans la même page.
PHP s'est lancé exactement comme BASIC, les programmeurs débutant s'y lancent sans prérequis de programmeurs, sans connaissances approfondis ou naicéssaires du langage PHP ou HTML et sans même la connaissance suffisante de l'environnement PHP, du serveur Web le motorisant.
Certains abordent l'approche base de données (MYSQL souvent) sans connaisance du modèle relationnel.
Ils avancent avec les erreurs.

Cette approche de PHP, prétend à tord servir le programmeur. Certes, PHP peut être assimilé à BASIC, mais le programmeur doit faire des efforts pour mieux le connaitre avec le temps en étendant ses connaissances et son savoir-faire sur les domaine connexes (configuration de l'environnement, spécialité de HTML, spécialité du SGBDR, ...)

L'approche Objet est souvent absente, les programmeurs croient à tord que ce domaine est floue voir difficile à aborder où alors c'est un terrain professionnel difficile d'accès.

Ne soyons pas péssimiste, le modèle objet clarifie et organise la solution.
C'est une approche conceptuelle plus qu'elle n'est une technique de programmation. Une solution sans méthodologie conceptuelle n'est pas construite sur des bases solides.

PHP OBJET permet de remplir ce vide conceptuel. Le programmeur a deux cassequettes alors :
"L'analyste" et "le programmeur" = "le développeur de solutions"

Un exemple conceptuel :
Dans un environnement client/serveur Web, les fonctions doivent se spécialiser :
Le Client : gére le dialogue avec utilisateur et avec le serveur
Le Serveur : (Main) oriente les tâches vers un module de traitement (décision, calcul ...) et/ou un système spécialisé dans le traitement de données (SGBDR, système de fichiers ...)

Les modules de traitement sont des objets spécialisés qui peuvent se diviser en deux types :
- Des objets métiers
- Des objets techniques (services)


Les objets métiers se consacrent aux traitements de requêtes de données métiers. Ils prennent en charge les communications avec le SGBDR (la base de données métier)
Ces objet doivent être ouverts, ils reçoivent des requêtes et revoient des données non formatées. ce qui rend leurs méthodes de fonctionnement totalement indépendantes de celles de leurs environnement (client, le module maitre (main), ou autres objets techniques...)

C'est là même la définition d'un objet, qui doit être architecturé (modélisé selon une classe unique), autonome, ouvert(interfaçable, régulable et senssibles aux évennements et execptions), réutilisable, extenssible, facilement maintenable et abstrait par rapport au langage de programmation.

Le niveau d'abstraction d'une classe d'objet est forcement élevé par-rapport à l'objet réellement exécutable dans un environnement physique.
C'est une pur approche analytique à la base de l'objet.

Dans le cadre d'une architecture 3-tiers, le modèle objet peut être conçu de la façon suivant en utilisant PHP.

1. HTML/et le script-côté-client (javascript ou vbscript) qui représentent le client : Un objet Client doit donc se pécialiser dans le dialogue bi-directionnel utilisateur/serveur

2. PHP étant le script exécuté côté serveur doit servir à créer des objets serveurs spécialisés notamment : le maitre d'opérations (main), l'objet base de données métier et d'autres objets techniques qui coopérent pour effectuer des actions techniques (calcul, organisation et formatage des données, gestion des exéceptions, des sessions et des paramètres reçus du clients...)

Voici un exemple où tout est objet :
Description de la Solution :
Le client se connecte en donnant son login et mot de passe, le serveur reçoit ses paramètres, intérroge la base de données des comptes logée sous MYSQL et communique au client le résultat qu'il attend. Deux résultats sont attendues :
Règle d'emission du résultat :
  • 1. Si la connexion est approuvée le client se voit redérigé vers le site d'accueil
    2. Dans tous les cas d'erreurs ou de connexion non approuvée, le résultat est un message explicatif selon le cas.
Selon une approche objet, les rôles des objets vont se définir et ainsi définir la classe de l'objet lui même à partir des besoins exprimés ci-dessus comme des objectifs.

C'est une analyse ascendante qu'il faut entreprendre pour construire les classes d'objets.

1. Cerner les fonctionnalités qui permettent de réaliser un certain nombre d'objectifs non héterogènes dans un même groupe
A cette étape on peut déjà séparer deux groupes :
a. l'interface qui permet au client d'envoyer son login et mot de passe et
de recevoir un message d'erreur venant du serveur

b. la validation de la connexion en recevant les paramètres (login et mot de passe) de l'utilisateur et en décidant de l'action résultat
On peut parler ici d'une table de décision, qui représente conceptuellement parlant les contraintes ou règles de gestion et qui selon la méthode booléenne, est représentée par une étude d'états logiques de plusieurs variable logiques afin de déclencher des actions (physiqument représentée par la structure conditionnelle SI ou IF)
On sait que pour qu'une décision soit prise une condition logique doit être évaluée.

Dans ce cadre, on peut sudiviser le groupe "b" en deux types de rôles :
b1. est la table de décision selon l'état logique retourné par la fonction de validation des connexion (cf. la règle d'emission du résultat)

b2. permet à b1 de décider en validant la connexion à partir de la base des comptes

Selon ce découpage simple, 3 objets surgissent :

OBJET FORM : groupe a (interagit avec b1) spécialisé dans l'affichage et la capture des paramètres utilisateur

OBJET CONNEXION : groupe b1 (interagit avec a et b2) et décide de l'action à faire selon l'état de validation de la connexion

OBJET COMPTE : groupe b2 (interagit avec b1) spécialisé dans l'interaction avec la base de données

L'objet CONNEXION est le programme maitre d'opérations puisqu'il joue le rôle d'intemédiaire entre (a) l'utilisateur et (b) le SGBDR
En créant une instance de cet objet le système de validation démarre, en démarrant l'objet (a) et en intérrogeant (b2).

Les principaux flux de données entre Objets sont :
f1 : Paramètres de connexion prévalidés (contiennent des données) envoyés par (a) à (b2) via (b1)
f2 : Etat logique d'acceptation ou pas de la connexion envoyé par (b2) à (b1)
f3 : Message d'erreur envoyé par (b1) vers (a) dans le cas d'un f2 faux
f4 : Entête HTTP contenant le document d'accueil, dans le cas d'un f2 vrai

Bien entendu, d'autres flux peuvent exister.

Les classes d'objets :
Toutes les classes sont écrites dans la page : mes_classes.cls
Vous pouvez ajouter des modificateurs "public ou private" aux membres
des classes pour les publier ou pas.
N.B: que dans ce site Objet exemple, il n'ya que la page de démarrage
connexion.php et la page mes_classes.cls qui contient toutes les ressources (ou pages) du site sous forme de classes.
Il est aussi possible de créer une seule classe modèle de page HTML dont
peuvent hériter toutes les autres classe à caractère "interface utilisateur".

<?php
//Objet a: définissant le comportement de l'interface utilisateur

Code : Tout sélectionner

class form { var $login; var $motDePasse; var $message; var $fin; //Construction d'un formulaire function form() { //si des paramètres sont issus du précedent dialogue //alors Pré validation $this->login = null; $this->$this->motDePasse = null; $this->fin = false; if (!isset ($_POST["login"]) || trim($_POST["login"]) == "" ) $this->message = "Login obligatoire!"; else if (!isset ($_POST["motDePasse"]) || trim($_POST["motDePasse"]) == "" ) $this->message = "Mot de passe obligatoire"; else { //login et mot de passe correctement passés $this->login = $_POST["login"]; $this->motDePasse = $_POST["motDePasse"]; } } function afficher() { echo " <h1>Connexion</h1> <form method=post> <table> <tr><td>Login* <td><input name=login value=$this->login> <tr><td>Mot de passe* <td><input type=password name=motDePasse> <tr><td colspan=2><input type=submit value=Ok> <input type=reset value=Effacer> <tr><td colspan=2><div id=message>$this->message</div> </table> </form>"; } }
//Objet b1: définissant le comportement de la validation de connexion

Code : Tout sélectionner

class connexion { //interlocuteur principal avec l'objet (a) form et l'objet (b2) compte var $form; var $compte; //Construction de l'objet function connexion() { //Démarre la validation des connexions $this->valider(); } //Gérer le dialogue utilisateur function valider() { //En créant un objet form, des paramètres de la session précédente // sont capturés et validés s'ils existent $this->form = new form(); if ($this->form->login != null && $this->form->motDePasse != null) { //Valider la connexion $this->compte = new compte(); //passage du flux f1 $this->compte->login = $this->form->login ; $this->compte->motDePasse= $this->form->motDePasse; //Demande d'approbation (Table de décision) et flus f2 if ($this->compte->approuvé()) { //Ouvrir le site pour une bonne connexion (flux f4) $_SESSION["compte"] = $this->compte; //Arrêt du dialogue = accès à la page d'accueil $this->form->fin = true; } //envoyer un message pour une mauvaise connexion (flus f3) else $this->form->message = "Connexion échouée!"; } //Afficher le formulaire de dialogue if (!$this->form->fin ) $this->form->afficher(); } }
//L'objet b2 : gére les comptes utilisateurs

Code : Tout sélectionner

class compte { //source de données var $source; //Identité d'un utilisateur var $login; var $motDePasse; var $nom; var $email; //construction de compte = relier l'objet à une source de données function compte() { $this->source = mysql_connect("localhost","root",""); if (!$this->source) $this->source = null; else if (!mysql_select_db("ma_base", $this->source)) $this->source = null; } //Approuver un utilisateur function approuvé() { //erreur de connexion if ($this->source == null ) return false; //Vérifier si l'utilisateur identifié par le login et motdePasse existe $sql = "SELECT nom, email FROM compte WHERE login='$this->login' AND motDePasse = '$this->motDePasse'" ; $reponse = mysql_query($sql,$this->source); if (mysql_num_rows($reponse) > 0) { //completer les informations approuvées $user = mysql_fetch_object($reponse); $this->nom = $user->nom; $this->email = $user->email; return true; } else return false; } }
//Objet accueil: définissant la page d'accueil autorisée pour les connexions valides

Code : Tout sélectionner

class accueil { //Compte d'accès à cette page var $compte; var $message; //Construction de la page function accueil() { //Accès autorisé si un compte est passé par la session $this->compte = null; if (!isset ($_SESSION["compte"])) $this->message = "Page sécurisée, connectez-vous!"; else { //Récupérer le compte $this->compte = new compte(); $this->compte = $_SESSION["compte"]; } $this->afficher(); } function afficher() { if ($this->compte != null) { $nom = $this->compte->nom; echo " <h1>Accueil</h1> bienvenue $nom "; } else echo "<div id=message>$this->message</div>"; } }
?>

Pour Exécuter la validation des connexion il suffit de créer une instance de l'objet (b1) connexion puisqu'il est programmé pour construire un dialogue entre l'utilisateur (a) et la base des comptes (b2)

Exemple de page de démarrage :
Page connexion.php

Code : Tout sélectionner

<? session_start(); //Exemple de page de démarrage : //Page connexion.php include_once "mes_classes.cls"; $connexion = new connexion(); //Si le dialogue s'arrête = la connexion est valide = accès à la page d'accueil if ($connexion->form->fin) $accueil = new accueil(); ?>
Remarque : la page de démarrage inclus la page "mes_classes.cls" qui
contient toutes les classes, cette page est chargée une fois, Cependant
selon l'avancement de l'algorithme l'interpréteur n'a pas besoin de la
description de toutes les classes, il est possible alors de diviser la page
des classes en plusieurs pages et ne les charger qu'en cas de besoin.

Petit nouveau ! | 7 Messages

15 févr. 2005, 12:00

Code : Tout sélectionner

class form { var $login; var $motDePasse; var $message; var $fin; //Construction d'un formulaire function form() { //si des paramètres sont issus du précedent dialogue //alors Pré validation $this->login = null; $this->$this->motDePasse = null; $this->fin = false; if (!isset ($_POST["login"]) || trim($_POST["login"]) == "" ) $this->message = "Login obligatoire!"; else if (!isset ($_POST["motDePasse"]) || trim($_POST["motDePasse"]) == "" ) $this->message = "Mot de passe obligatoire"; else { //login et mot de passe correctement passés $this->login = $_POST["login"]; $this->motDePasse = $_POST["motDePasse"]; } } function afficher() { echo " <h1>Connexion</h1> <form method=post> <table> <tr><td>Login* <td><input name=login value=$this->login> <tr><td>Mot de passe* <td><input type=password name=motDePasse> <tr><td colspan=2><input type=submit value=Ok> <input type=reset value=Effacer> <tr><td colspan=2><div id=message>$this->message</div> </table> </form>"; } }

Ca me rappelle étrangement quelque chose :?
Espérons qu'il s'agisse juste d'une coïncidence...

ViPHP
ViPHP | 1024 Messages

15 févr. 2005, 12:11

Je suis d'accord sur le fond ( il faut coder dans des classes et utiliser des objets ) mais pas dans la forme ( l'article est indigeste, désolé, et il manque la séparation de l'affichage ).

L'architecture que je conseille:
- templates pour gérer les affichages ( PHPlib )
- objets/classes pour tous les traitements métier
- page faisant les tests (dialogues) et utilisant les objets/méthodes, puis générant l'affichage

( à suivre ... )

Pascal

Eléphant du PHP | 441 Messages

23 févr. 2005, 12:56

Très bon topique même si difficile à appréhender.
J'ai justement une application Client http avec une archi 3tiers en utilisant php.
Et bon ce topic répond partiellement à certaine de mes question mais je bute toujours sur l'affichage...comment séparer réellement l'affichage?
Pascal tu parles de template, tu pourrais développer un peu plus stp ou me rediriger vers un autre topic STP?

merci d'avance

ViPHP
ViPHP | 1024 Messages

23 févr. 2005, 20:34

Très bon topique même si difficile à appréhender.
J'ai justement une application Client http avec une archi 3tiers en utilisant php.
Et bon ce topic répond partiellement à certaine de mes question mais je bute toujours sur l'affichage...comment séparer réellement l'affichage?
Pascal tu parles de template, tu pourrais développer un peu plus stp ou me rediriger vers un autre topic STP?

merci d'avance
Il n'y a pas une indépendance complète entre les données et l'affichage, faut pas rever mais les templates ça aide:

le fichier template contient le html et des variables au format {JE_SUIS_UNE_VARIABLE} ;

dans la page php, on fait les tests pour savoir quel traitement faire (on verifie les variables en session, les posts et get...);
ensuite on fait le traitement, qui est un appel objet (ça limite le code dans la page); et on prepare les valeur pour les donnees que l'on doit afficher;
on determine quel affichage utiliser;

on parcours le template et on fait la correspondance valeur <=> {variable}

ça permets quoi?

- avoir les traitements métiers dans des classes, et là on gagne du temps car avec les bases de données c'est quasi toujours la même histoire (update, select, insert, verif...)
- avoir les affichages dans des fichiers templates qui ne sont que du html, donc on peut faire un truc basique html lors du dev, puis une fois que c'est pret s'y ( penser ) pencher reellement (ou le filer à un graphiste)
- avoir un code limité dans la page, donc plus facile à reprendre

voilà en gros.

A+

Pascal
Modifié en dernier par pascaltje le 25 févr. 2005, 21:08, modifié 1 fois.

Eléphant du PHP | 441 Messages

24 févr. 2005, 13:03

ok merci :D
Reste plus qu'à bien structurer les classes!!

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

01 mars 2005, 18:15

Le topic que j'ai envoyé n'est qu'un exemple simplifié de l'utilisation d'objets en PHP.
Effectivement il faut créer des classes techniques spécialisées et ainsi automatiser
la majorité des fonctionnalités connues dans les contextes de dialogue avec les base de données
et l'utilisateur final (ex: une classe spécialisée dans le codage HTML)

Ainsi, tout affichage HTML telque :
* Formulaire
* Grille
Peut être automatisé et créé dynamiquement à partir d'une source de données (un schèma de

données)

Je m'explique par un exemple :
On va dire que le formulaire contient une grille de données, il soustraite donc les services

d'une grille. Mais il construit lui même son contexte de dialogue : une méthode de postage, une

destination de traitement CGI, une action submit et une barre d'état.

Prenons l'exemple d'un formulaire d'inscription d'un membre.
Les données sont disposées en lignes avec un entête de lignes, comme :

Code : Tout sélectionner

NOM |------------------| PRENOM |-----------------------|
etc.

Le formulaire dans ce cas contient une grille de 2 colonnes dont la première joue le rôle

d'entête de lignes, la seconde est porteuses de données affichées ou à saisir.

En changeant de disposition, le même formulaire présente cette fois ses données en colonnes,

comme :

Code : Tout sélectionner

NOM PRENOM |------------------| |-----------------------|
etc.

Le formulaire dans ce cas contient une grille de 2 lignes dont la première joue le rôle d'entête

de colonnes, la seconde est porteuses de données affichées ou à saisir.


Les données peuvent être transmis à la grille via des objets "zone" de différents types :
Des données modifiables (zone de texte, liste déroulante...)
ou des données "STATIQUE" en affichage seul.

Chaque zone est identifiée par son nom, son titre, son type et ses valeurs
N.B: que chaque zone porte sa liste de valeurs.

En créant une liste d'objets "Zone", la grille doit les disposer selon un type de disposition
(en lignes ou en colonnes)

La grille construit son contenu selon les valeurs des zones contenues dans la liste des zones
Elle construit son entête (de lignes ou de colonnes selon la disposition choisie) à partir des

titres des zones.

Par extension, le formulaire contient une grille, qui contient une liste de zones, dont une zone

est porteuse d'une liste de valeurs et de son identité (nom, titre et type)

A partir delà, on peut construire des grilles à deux orientations (données en lignes ou en

colonnes) et contenant plusieurs valeurs pour chaque données.

Exemple :
Grille dont les données sont disposées en colonnes :

Code : Tout sélectionner

Réf Désignation Pu Qté valeur |---| |-----------| |----| |---| |-----| |---| |-----------| |----| |---| |-----| |---| |-----------| |----| |---| |-----| |---| |-----------| |----| |---| |-----|
ou :
Données en lignes :

Code : Tout sélectionner

Réf |---| |---| |----| |----| Désignation |-----------||-----------||-----------||-----------| Pu |----| |----| |----| |----| Qté |----| |----| |----| |----| valeur |----| |----| |----| |----|

Il suffit donc de fournir une liste de zones à la grille, cette dernière affiche alors toutes les

valeurs de chaque zone selon une orientation définie.

Les principales classe sont :
La classe form : le formulaire qui encaplsule un objet grille
La classe grille : la grille qui encapsule une liste de zones de données à afficher
La classe zone : qui définit une données et ses valeurs (chaque zone a une liste de valeurs)

Le programme d'exemple qui met en oeuvre ce concept de classes techniques spécialisées dans
l'affichage (formulaire et grille) est le suivant:

Ce programme simule le fonctionnement d'une page de connexion d'un membre.
Il affiche un formulaire de connexion, intercepte les données postées et valide la connexion.
Dans le cas où une connexion est approuvée, il affiche la page d'accueil (selon un modèle html).

Les classes sont commentées et disposent de toutes les fonctionnalités qui les rendent
autonomes.
<?
class zone {
  var $nom;
  var $titre;
  var $type;
  var $valeurs;
  public function zone() {
      $this->nom = "Zone1";
      $this->titre =  "Zone1";
      $this->type = "STATIQUE";
	  //$this->ajouterValeur("");
  }
  public function ajouterValeur($valeur) {
		$rang = count($this->valeurs);
    	$this->valeurs[$rang] = $valeur;
  }
  public function valeurExiste($une_valeur) {
     $position = 0;
	 if ($this->valeurs != null)
      foreach ($this->valeurs as $valeur){
	   	if ($valeur == $une_valeur) return $position;
	 	$position ++;
	 }
	 //Autres cas
	 return false;
  }
  public function supprimerValeur($valeur) {
    $position = $this->existe($valeur);
	//supprimer si existe
	if ($position != false) {
		//suppression à la position trouvée
		unset ($this->valeurs[$position]);
		//Réindexation de la liste des zones
		$this->valeurs = array_values($this->valeurs);
		return true;
	}
  }
  public function effacerValeurs(){
  	for ($v=0; $v<count($this->valeurs); $v++)
		$this->setValeur($v,"");
  }
  public function setValeur($rang , $valeur){
	if ($rang >=0 && $rang < count($this->valeurs)) 
		$this->valeurs[$rang] = $valeur;
  }
  public function getValeur($rang = 0){
    //Par défaut le rang retourné est le premier s'il existe
	if ($rang >=0 && $rang < count($this->valeurs)) 
		return $this->valeurs[$rang];
	else return null;
  }
  public function vider() {
  	unset ($this->valeurs);
  }
  public function setValeurs($liste_valeurs){
  	$this->vider();
  	for ($v=0; $v<count($liste_valeurs); $v++)
		$this->ajouterValeur($liste_valeurs[$v]);
  }
  public function getValeurs(){
  	return $this->valeurs;
  }
}//fin de la classe zone

class grille {
  var $zones;
  var $orientation;
  public function grille() {
    $this->orientation = "EN_LIGNES";
  }
  public function ajouter($zone) {
  	//ne pas ajouter un doublon de $zone
    if ($this->existe($zone->nom) == false) {
		$numZone = count($this->zones);
    	$this->zones[$numZone] = new zone();
    	$this->zones[$numZone] = $zone;
		return true;
	}
	//autres cas : non ajouté
	return false;
  }
  public function existe($nom_zone) {
     $position = 0;
	 if ($this->zones != null)
      foreach ($this->zones as $zone){
	   	//cas de zone trouvée
	   	if ($zone->nom == $nom_zone) return $position;
	 	$position ++;
	 }
	 //Autres cas
	 return false;
 }
   public function getZone($nom_zone) {
	 if ($this->zones != null)
      foreach ($this->zones as $zone)
	   	//cas de zone trouvée
	   	if ($zone->nom == $nom_zone) return $zone;
	 //Autres cas
	 return null;
 }
  public function supprimer($nom_zone) {
    $position = $this->existe($nom_zone);
	//supprimer si la zone existe
	if ($position != false) {
		//suppression à la position trouvée
		unset ($this->zones[$position]);
		//Réindexation de la liste des zones
		$this->zones = array_values($this->zones);
		return true;
	}
	//autres cas
	return false;
  }
  //Pour effacer toutes les valeurs de une ou toutes les zones 
  //l'argument $nom_zone est optionnel (valeur par défaut = vide => toutes les zones)
  //l'argument $valeur est optionnel (vide=toutes les valeurs) : sert à cibler une valeur précise d'une zone donnée
  public function effacer($nom_zone = "") {
     if ($this->zones != null )
      if ($nom_zone == "")
	  	foreach ($this->zones as $zone)
	    	$zone->effacerValeurs();
	  else {
	  		$zone =$this->getZone($nom_zone);
		 	if ($zone != null) $zone->effacerValeurs();
			}
  }
  public function setValeur($nom_zone,$rang, $valeur) {
  		if ($nom_zone != ""){
			$position_zone = $this->existe($nom_zone);
			if ($position_zone != false) 
				$this->zones[$position_zone]->setValeur($rang, $valeur);
		}
  }
  public function setValeurs($nom_zone,$liste_valeurs) {
  		if ($nom_zone != ""){
			$position_zone = $this->existe($nom_zone);
			if ($position_zone != false) 
				$this->zones[$position_zone]->setValeurs($liste_valeurs);
		}
  }
  public function getValeur($nom_zone,$rang) {
  		if ($nom_zone != ""){
			$position_zone = $this->existe($nom_zone);
			if ($position_zone != false) 
				return $this->zones[$position_zone]->getValeur($rang);
		}
		return null;
  }
  public function getValeurs($nom_zone) {
  		if ($nom_zone != ""){
			$position_zone = $this->existe($nom_zone);
			if ($position_zone != false) 
				return $this->zones[$position_zone]->getValeurs();
		}
		return null;
  }
  public function afficher() {
    if ($this->zones != null) {
	  //Construire l'entête de la grille (à partir des titres de zones)selon l'orientation 

choisie
	  $ligne = 0; $colonne = 0;
      foreach ($this->zones as $zone) 
          if ($this->orientation == "EN_LIGNES") {
	  			//Données en lignes => la colonne 0 est l'entête de lignes
                $grille[$ligne][0]= "<th>".$zone->titre;
				//Evolution en lignes
				$ligne ++;
		  }
		  else {   
	  		//Données en colonnes => la ligne 0 est l'entête de colonnes
		  	$grille[0][$colonne]= "<th>".$zone->titre;
			//Evolution en colonnes
			$colonne ++;
		  } //fin if et foreach

	  //Construire les céllules détails (données) de la grille à partir des valeurs des zones	

 
      //Selon l'orientation, les valeurs commencent à partir de ligne et colonne précises
	  if ($this->orientation == "EN_LIGNES") {$ligne = 0; $colonne = 1; }
	  else {$ligne = 1; $colonne = 0;}
	  //Le contenu des céllules est défini pour toutes les valeurs zone/zone
      foreach ($this->zones as $zone) {
	   //Crrection si une zone n'a pas de valeur définie
	   if ($zone->valeurs == null) $zone->ajouterValeur("");
	    foreach ($zone->valeurs as $valeur){
		//La structure d'une céllule est définie selon le type de la zone
	  	switch ($zone->type) {
	   		case "ZONE_TEXTE" :
                 	$cellule = "<td><input type='text' name='".$zone->nom."[]' 

value='".$valeur."'>";
	  		break;
      		case "MOT_DE_PASSE" :  
					//Pas de rappel de valeur pour le mot de passe    
                 	$cellule =  "<td><input type='password' name='".$zone->nom."[]' 

value=''>";
	  		break;
	  		default :
	  	   		//le mode d'affichage par défaut est : "STATIQUE" (lecture seule)
				//Un champ caché est ajouté pour pouvoir poster la valeur d'une 

céllule statique
              	$cellule =  "<td>".$valeur."<input type='hidden' name='".$zone->nom."[]' 

value='".$valeur."'>";				 
	   } //fin switch
	   //Mettre à jour la grille => placer la céllule à sa place (ligne/colonne en cours)
	   $grille [$ligne][$colonne] = $cellule;
	   
	   //Valeur suivante de la même zone... => ligne ou colonne suivante selon l'orientation
		if ($this->orientation == "EN_LIGNES") $colonne ++; else $ligne ++;	  
      } //fin foreach $zone->valeurs 
	  
	  //Zone suivante... => ligne ou colonne suivante selon l'orientation
	  //Avec retour à la ligne ou colonne de début pour la nouvelle zone
	  if ($this->orientation == "EN_LIGNES") {$ligne ++; $colonne = 1;}
	  else {$ligne = 1; $colonne ++;} 
	  }//fin foreach $this->zones
	  //Fin de remplissage de la grille, ce qui reste à faire est de l'afficher'
      //Ouvrir la table HTML
	  echo "<table>";
	  //La première dimension de la grille contient les lignes
	  foreach ($grille as $ligne) {
	    //Créer une ligne de table
	    echo "<tr>";
		//Chaque ligne contient des colonnes (ou céllules)
	  	foreach ($ligne as $cellule)
			echo $cellule;
	  }
	  //Fermer la table HTML
      echo "</table>";
	 }//fin if
  } //fin fonction afficher
}//fin class grille

class form  {
 var $nom;
 var $titre;
 var $méthode;
 var $déstination;
 var $action;
 var $contenu;
 var $message;

 public function form() {
   $this->nom = "form1";
   $this->titre = "Form1";
   $this->méthode = "Post";
   $this->action = "";
   $this->message="";
   $this->contenu = new grille();
 }
 public function afficher() {
   //Aprés un postage précédant éventuel
   //Récupérer les données postées
   $this->getContenu();
   //Récupérer l'action effectuée  
   $this->action = $this->getPostage("action");
   if ($this->action != null) 
   	    if ($this->action == "Effacer") {
	    		$this->contenu->effacer();
				$this->message = "Formulaire éffacé";
			}
   //Afficher l'entête du formulaire		
   echo "<h1>".$this->titre."</h1>
            <form name='".$this->nom."' method='".$this->méthode
           ."' action='".$this->déstination."' >";
   //La grille de contenu
   $this->contenu->afficher();
   //Les actions et la barre d'état (message)
   echo "<table><tr><td>
         <input type=Submit value=Envoyer name=action onClick='return post();'>
         <input type=Submit value=Effacer name=action>
		 <tr><td><div id=message>".$this->message."</div>
         </table></form>
		 <script>
		 	function post() {
			    //En cas d'attente de la réponse du serveur
				document.all[\"message\"].innerText=\"Envoi en cours...\";
				return true;
			}
		 </script>";             
 }
 //Récuperer le contenu posté
 public function getContenu() {
 	  //Traiter zone/zone
      foreach ($this->contenu->zones as $zone) {
	    //Récupérer la liste des valeurs postées pour la zone traitée
	  	$parametre = $this->getPostage($zone->nom);
		//Mettre à jour les valeurs de la zone
	    if ($parametre != null)
			$zone->setValeurs($parametre);
	  }
 } 
 //Récuperer le postage
 public function getPostage($parametre) {
 	//Selon la méthode de postage : réciupérer un paramètre par son nom
 	switch ($this->méthode) {
		case "Post" : return isset($_POST["$parametre"])?$_POST["$parametre"]:null;
		case "Get" : return isset($_GET["$parametre"])?$_GET["$parametre"]:null;
		default : return null;
	}
 }
}//fin classe form

class membre {
var $login;
var $mdp;
var $nom;
var $prénom;
var $fonction;
var $email;
//Base de données des membres
var $liste;

public function charger() {
    //vider la liste
	$this->liste = null;
	
	//Des données exemple, pour des soucis de test : 
	//normalement il faut remplir la liste des membres à partir d'une base de données
	$this->nom = "root";
	$this->mdp = "root";
	$this->nom = "toto";
	$this->prénom = "toto";
	$this->fonction = "Administrateur";
	$this->email ="root@localhost";
	$this->ajouter();
}
public function ajouter() {
  if (!$this->existe()) {
	$rang = count($this->liste);
	$this->liste[$rang] = new membre();
	$this->liste[$rang] = $this;
	}
}
public function existe (){
  if ($this->liste != null)
   foreach ($this->liste as $membre)
	if ($membre->login == $this->login && $membre->mdp == $this->mdp) {
		$this->nom = $membre->nom;
		$this->prénom = $membre->prénom;
		$this->fonction = $membre->fonction;
		$this->email = $membre->email;
		return true;
	}	
  return false;  
}
}//fin classe membre

class connexion extends form {
	public function connexion() {
		//Construit le formulaire à partir du parent form
		$this->form();
		//Fixer les propriétés du formulaire
		$this->nom = "fconnecter";
		$this->titre ="Connexion";
        
		//Et de son contenu
		$zone = new zone();
		$zone->nom = "login";
		$zone->titre = "Login *";
		$zone->type = "ZONE_TEXTE";
		$this->contenu->ajouter($zone);

		$zone = new zone();
		$zone->nom = "mdp";
		$zone->titre = "Mot de passe *";
		$zone->type = "MOT_DE_PASSE";
		$this->contenu->ajouter($zone);
		
		$zone = new zone();
		$zone->nom = "fonction";
		$zone->titre = "Fonction *";
		$zone->type = "ZONE_TEXTE";
		$zone->ajouterValeur("Administrateur");
		$this->contenu->ajouter($zone);
		
		//Choisir une orientation
		$this->contenu->orientation = "EN_LIGNES";
		//ou 
		$this->contenu->orientation = "EN_COLONNES";
		
		
	}
	//Objectif du formulaire : autoriser ou non une connexion
	public function estAutorisée() {
	    //Récupérer les données postées
		$this->getContenu();
		//Vérifier s'il s'agit d'un membre connu
		$membre = new membre();
		$membre->charger();
		$membre->login =$this->contenu->getZone("login")->getValeur();
		$membre->mdp = $this->contenu->getZone("mdp")->getValeur();
		if ($membre->login != "" && $membre->mdp != "" && $membre->existe()){ 
			 $_SESSION["membre"]= $membre;
			 return true;
			 }
		else {
			$this->message = "Veuillez saisir un login et un mot de passe, 

correctes!";
			return false;
		}
	}
	
}//fin de la classe connexion

class accueil  {
var $modèle;
var $contenu;
var $membre;	
   public function accueil() {
		$this->membre = isset($_SESSION["membre"])?$_SESSION["membre"]:null;
		if ($this->membre != null) {
	    	$this->modèle ="accueil.php";
			//Insérer l'identité du membre dans la page modèle
			//où il y'a normalement deux champs de fusion ($nom et $prénom)
			$nom = $this->membre->nom;
			$prénom = $this->membre->prénom;
			
			//afficher la page
			include $this->modèle;
		}
		else echo "Désolé, vous n'êtes pas autorisé à accèder à cette page!";
	}
}//fin classe accueil

//Programme de démarrage
//Démarrer le gestionnaire de sessions
session_start();
//Utiliser un form. de connexion  existant dans la session ou  créer un nouveau
$connexion=isset($_SESSION["connexion"])?$_SESSION["connexion"]:new connexion();
//Afficher le form. de connexion
if (!$connexion->estAutorisée()) $connexion->afficher();
//else echo "Vous êtes autorisé!";
else new accueil();
//Mettre à jour la session
$_SESSION["connexion"] = $connexion;
?>

Et finalement la page modèle "accueil.php" :
<html >
<h1>Bienvenue</h1>
<P><B><? echo "$prénom $nom"; ?></B>
<hr>
</html>
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

ViPHP
ViPHP | 1024 Messages

01 mars 2005, 18:39

par pitié, utilise le bouton PHP pour mettre en couleur le code!

je suis totalement contre la notion de grille, de zone et de formulaire généré de cette manière:
- on ne peut faire que des formulaires rentrant dans le moule de la classe, si on veut adapter à un contenu plus riche, bibi doit recoder le bazar
- on a aucun aperçu visuel du rendu, on ne peut pas modifier le rendu avec un éditeur html (on perd l'attrait du html)
- si on a un graphiste sous la main, on devra recoder ses maquettes avec la classe

je suis pour une approche template (= des fichiers contenant le html de manière séparée du code):
- on a du html, modifiable simplement et à volonté
- on peut faire des formulaires simples ou très poussés, sans autre contrainte que son niveau en html/javascript
- on peut écrire un tableau html moche lors du dev et une fois que le lien avec les données est OK, on améliore la page indépendamment de la prog PHP
- la graphiste peut faire les fichiers html en plus du café
- l'architecture est séparée entre la présentation et le métier

ViPHP
fab
ViPHP | 2657 Messages

01 mars 2005, 20:33

Je suis d'accord sur le fond ( il faut coder dans des classes et utiliser des objets ) mais pas dans la forme ( l'article est indigeste, désolé, et il manque la séparation de l'affichage ).

L'architecture que je conseille:
- templates pour gérer les affichages ( PHPlib )
- objets/classes pour tous les traitements métier
- page faisant les tests (dialogues) et utilisant les objets/méthodes, puis générant l'affichage

( à suivre ... )

Pascal
Je suis pas le seul a utiliser ce type d'architecture :)

ViPHP
ViPHP | 1024 Messages

01 mars 2005, 20:39

Je suis d'accord sur le fond ( il faut coder dans des classes et utiliser des objets ) mais pas dans la forme ( l'article est indigeste, désolé, et il manque la séparation de l'affichage ).

L'architecture que je conseille:
- templates pour gérer les affichages ( PHPlib )
- objets/classes pour tous les traitements métier
- page faisant les tests (dialogues) et utilisant les objets/méthodes, puis générant l'affichage

( à suivre ... )

Pascal
Je suis pas le seul a utiliser ce type d'architecture :)
et j'étudie en ce moment le remplacement des formulaires en POST par une utilisation des XmlHttpRequest... donc rien n'est figé ;)

ViPHP
fab
ViPHP | 2657 Messages

01 mars 2005, 21:05

pourquoi pas :) , par contre sel différence que j'ai avec ton architecture c'est PHPlib j'utilise des fonctions d'un amis super pratique

PS : aussi j'ai un micro systeme de cache maison :)