Page 1 sur 1

modelisation espace membre

Posté : 18 nov. 2005, 16:15
par jeff
salut
en attendant le sujet de liquid sur le MCV
je vais refere mes class pour un espace privé
je pensais faire une class Groupe qui concerne les membre d'un meme groupe(gerer les droit sur une base)
attribut
  • private groupName
    private passData
et comme methode
  • public __construct()
    public getGroupe()
    public setGroupe($groupName,$mdp_data)
    public newGroupe($groupName,$mdp_data)
    public deleteGroupe($groupName)
    public editGroupe($groupName)
et une class User derive de Groupe avec
attribut
  • protected login
    protected mdp
    public auth
et un peut pres les memes methode
avec en plus
  • public verifUsers($login,$mdp) extends Groupe::getGroupe

    maintenant toute les infos pour construire c'est objet sont dans une db
    je ai une class pour me connecter a ma base
    celle ci se fait en deux temps
    ex
    $mysql = new  Mysqldb(SERVEUR,LOGIN,PASS,BASE);
    		$dao = new DAO($mysql);
    je n'ai pas de pas de methode statique (de toute facon je vois pas comment les utliser :? )

    est ce que je doit construire une liaison avec ma db pour chaque methode
    ou est ce que je doit ajouter un attribut a mes classe comme ceci
    $mysql = new  Mysqldb(SERVEUR,LOGIN,PASS,BASE);
    		$this->dao = new DAO($mysql); 
    si vous avez des idées merci
    et je sais que vous en avez :wink:
ps:comment relier la classe Users aux autre classe metier pour definir le droit d'acces de ces personnes sur la db :?:

Posté : 18 nov. 2005, 17:36
par Genius
Salut,

je pense tu veux qqch comme ca ...
$mysql = new  Mysqldb(SERVEUR,LOGIN,PASS,BASE); 
$dao = new DAO($mysql); 

class myClass
{
//..
setDao(&$dao)
{
$this->dao = $dao;
}
//..
}
?

Posté : 18 nov. 2005, 18:26
par Liquid
C'est quoi pour toi Group ? Une réunion de User ou une notion plus abstraite comme une liste de droits que différents User peuvent partager ?

Dans le premier cas un User "appartient à" un Group et un Group "contient" un ou plusieurs User. Illustration :

Code : Tout sélectionner

class Group auth : ? // partage par tous les User de ce Group users : array addUser(User) : void removeUser(User) : void class User auth : ? // Si ce User a un auth (?) particulier rien qu'a lui login : string pwd : string group : Group
Note : il y a des références croisées, un User a un champ Group dans lequel il est lui-même (la même instance) référencé !

Dans le deuxième cas un User "possède" un Group mais un Group ne "contient" pas de User. Illustration :

Code : Tout sélectionner

class Group auth : ? // partage par tous les User de ce Group class User auth : ? // Si ce User a un auth (?) particulier rien qu'a lui login : string pwd : string group : Group
La différence c'est qu'un Group (de droits) ne sait rien des utilisateurs.

Peut-être que tu veux faire quelque chose d'hybride mais il faudrait définir un plus ce que tu envisages de faire... Je pense que c'est plus proche du premier cas exposé ? Dans Group il faut ajouter les méthodes permettant d'accéder à auth (?).

Pour construire les objets, tu le fais à l'extérieur de ces classes, dans cette classe qui accède aux données tu peux éventuellement construire les objets mais le mieux est encore de séparer ce traitement. Quoi qu'il en soit la classe qui détient les données utilise les accesseurs getXxx() et setXxx() de Group et User pour les peupler.

Code : Tout sélectionner

class DAO getXxxData(Param) : ? class Processor execute() : void
où execute() fera :

Code : Tout sélectionner

execute(){ groupData = DAO::getGroupData(Param) group = Group() group->setXxx(groupData->aData()) userData = DAO::getUserData(Param) user = User() user->setXxx(userData->aData()) user->setGroup(group) group->addUser(user) }

quand la brume se leve petit à petit

Posté : 18 nov. 2005, 20:17
par jeff
merci
tres instructif :)

pour moi un groupe peu contenir un certain nombre d'user qui partagent les meme droits et les groupe sont hierachisés



j'ai juste une petite question sur ton code

Code : Tout sélectionner

groupData = DAO::getGroupData(Param) groupData->aData()
je comprend mal le role de groupData (recupere des données et les transmet??)


au fait pourqoui user ne pourrai pas derivé de Groupe

Posté : 19 nov. 2005, 12:08
par Liquid
Concrètement quand une classe hérite d'une autre, elle hérite de tout ou partie de son comportement (et données). Mais il ne faut pas oublier l'objectif de l'héritage, la spécialisation (autrement dit préciser un type). Or dans le cas d'utilisateurs et de groupes d'utilisateurs, un utilisateur n'est pas un groupe spécialisé, ce sont deux objets du monde réel très différents, ils ne décrivent pas la même chose ; un groupe contient des utilisateurs, un utilisateur appartient à un groupe.

Par contre tu peux très bien définir une hiérarchie de groupes. Dans la super classe il y aurait les méthodes permettant d'ajouter et d'enlever des utilisateurs, et la définition des droits communs à tous les groupes. Si tu as un type de droit particulier tu peux concevoir une sous-classe spécialisée définissant ce droit.

Code : Tout sélectionner

class Group users : array add(user) remove(user) class DBGroup extends Group // ...
Mais ce n'est pas forcément judicieux et ça ajoute une complexité dont on peut souvent se passer.
Le plus simple étant de définir toutes les propriétés dans Group, en prévoyant quand même une évolution possible donc Group peut être abstrait pour définir les méthodes communes :

Code : Tout sélectionner

abstract class AbstractGroup users : array add(user) remove(user) class Group extends AbstractGroup read : boolean write : boolean
Avec la solution "héritage" tu aurais deux sous-classes de AbstractGroup, par exemple ReaderGroup et WriterGroup, les propriétés read et write disparaissent et c'est le type qui informe du droit, le premier indique des utilisateurs qui ne peuvent que lire, le second écrire (donc lire).

Posté : 19 nov. 2005, 12:33
par jeff
pour avoir plus devisibilité sur ce que je fais voici la modelisation de la baseImage

on attribut des droits a un groupe donc aux utilisateur qui sont dedans

mais pour la navigation dans le site je veux enregistrer le login d'un user, son groupname et le mot de pass pour la db et une autre variable $log
dans une session (ou autre mecanisme plus adapter)

$log permet de savoir si l'utilisateur c'est bien authentifier par rapport a son groupe et les actions qui lui sont accordés

je ne sais pas si $log doit etre un attribut de user ou alors faire classe abstraite pour users avec login et mot de passe et une classe derive avec les droits

je precise comme meme une chose car je ne sais pas si c'est clair :
pour moi la class groupe "sert" a recupere les droit sur la base de donnée et la classe user permet de s'authentifier sur la partie privé du site

en passant une petite question sur le typage
	public function setGroupe(array $data)
	{
		$this->groupName=$data['groupname'];
		$this->mdpData=$data['mdp_data'];
	}

public function addUser(Users $user)
	{
		$this->user[]=$user;
	}
la premier methode ne fonctionne pas :evil:
et la deuxieme oui
pour sur php.net on retrouve les deux

Posté : 19 nov. 2005, 13:53
par Liquid
Fais attention à ne pas t'emmêler les pinceaux entre le relationnel et l'objet, ce sont deux mondes différents, les classes ne sont pas des "copies" des tables.

Pour faire le point sur un modèle MVC simplifié histoire de s'entendre sur les rôles des différentes classes imaginon un espace privé accessible par login et mot de passe avec un seul contrôleur (toutes les requêtes pointes vers ce contrôleur, la page index par exemple, en paramètre de la requête nous passons le nom de l'action à exécuter) :

- Page login :
Un formulaire avec 2 champs login et pwd, l'action du formulaire est "index.php?action=LoginAction"

- Le contrôleur :
Il gère toutes les requêtes. La première chose à savoir c'est si l'utilisateur est authentifié, c'est simple, si dans la session il y a un paramètre "user" non null alors le client est authentifié. (Le cas de l'action login est particulier, mais dans tous les autres cas si "user" est null alors le contrôleur redirige vers la page de login). Le contrôleur récupère le paramètre action, teste si c'est LoginAction, si oui il demande à une classe LoginAction de traiter la demande puis redirige en fonction du résultat retourner par LoginAction.

- La classe LoginAction :
Récupère les paramètres login et pwd, délègue à une classe d'accès aux données la requête qui retourne un résultat null si l'utilisateur n'est pas trouvé sinon un tableau contenant les informations sur l'utilisateur. Si un résultat non null est retourné alors LoginAction construit le User (éventuellement récupère d'autres données auprès de la classe d'accès aux données), stocke le User dans la session, retourne true (pour faire simple) pour indiquer au contrôleur que l'action a bien été exécutée.

- Retour au contrôleur :
L'action LoginAction s'est bien déroulée, le contrôleur redirige vers la page d'accueil de l'espace membre, l'action retourne false, le contrôleur redirige vers la page login.

Bon c'est très simplifié ! Il n'y a pas la gestion des erreurs (qui doivent éventuellement être affichées à l'écran), la construction de la vue, l'exécution éventuelle d'une autre action...

Imaginons que l'utilisateur est authentifié et envoie une requête depuis la page d'accueil "index.php?action=ShowUserListAction". Comme son nom l'indique, le résultat est l'affichage à l'écran de la liste de tous les utilisateurs. C'est au contrôleur (ou une/des classe(s) déléguées) de vérifier si l'utilisateur a le droit d'exécuter cette requête.
Dans un premier temps, le contrôleur vérifie dans la session que user n'est pas null, ensuite il récupère le paramètre action. Il vérifie que l'utilisateur a le droit par exemple avec if($user->isShowUserListAction()){...}else{...}.

Est-ce qu'on avance ? :) :wink:

Exemple de contrôleur (la page index.php) :

Code : Tout sélectionner

user = getParam("user") IF user is NULL actionPerformed = FALSE ELSE action = getParam("action") IF action is LoginAction actionPerformed = execute LoginAction ELSE IF action is ShowUserListAction IF user isShowUserListAction actionPerformed = execute ShowUserListAction ELSE actionPerformed = FALSE ... ELSE actionPerformed = execute LogoutAction DO actionPerformed
"actionPerformed" devrait être autre chose qu'un booléen, un objet par exemple :) . Car après l'exécution d'une action il faut savoir vers où rediriger l'utilisateur etc

Posté : 19 nov. 2005, 14:20
par jeff
le relationnel et l'objet, ce sont deux mondes différents,
ouai c'est vrai

je pensai pas qu'il falait decomposer autant pour moi il fallait juste avoir un objet user qui allait voir dans la table(grace a un dao) si l'utilisateur avait les droits ou non

pour l'instant je vais me contenter de finir mes classes groupe et user, pour la suite j'attends le mini tuto (ce que je ne comprennait pas c'etait la specialisation des objets et la difference de comportement, des objets metiers et des actions car pour l'instant dans mon code ca se croise )

ca avance :wink:

je suis en train d'essayer d'implement la class iterator pour Groupe

Posté : 19 nov. 2005, 14:55
par Liquid
Bah les droits ne sont pas des données qui changent tout le temps. On récupère les droits d'un utilisateur à la connexion et ils restent valables pendant toute la connexion. Si on change un droit, il faut "redémarrer" :idea: .

Mais bon c'est un autre problème.

L'accès aux données, l'affichage, les objets métiers etc ont chacun leur raison d'être. Si tu mélanges tout, tu perds en portabilité, évolutivité et même lisibilité. La question qu'il faut souvent se poser en OO, c'est "qui fait quoi ?".

Je ne sais pas trop ce que tu veux faire avec Iterator, ta classe Group n'est pas une structure de données ! Mais pour gérer un groupe d'utilisateurs il faut les regrouper dans une structure de données... Il ne faut chercher à itérer sur l'objet Group mais sur le tableau users (cf. le champ plus haut qui est un tableau) que tu récupères avec un getUsers().

Posté : 20 nov. 2005, 17:14
par jeff
tient voici un appercu des class (mais elle ne fonctionne pas encore ou c'est leur implementation :?: )

class Users
{
	private $login;
	private $mdp;
	private $auth;
	private $groupe;
	
	public function __construct()
	{	
		echo 'class: '.__CLASS__.'methode :'.__METHOD__.'<br/>';	
	}
	
	public function setUser($data)
	{
		$this->login=$data['login'];
		$this->mdp=$data['mdp'];
	}
	
	public function setGroupeUser(Groupe $data)
	{
		$this->groupe=$data;
	}
	
	public  function  getUser()
	{
		return $this;
	}
	
	public function __destruct()
	{
		echo 'class: '.__CLASS__.'methode :'.__METHOD__.'<br/>';
	}
}
class Groupe implements IteratorAggregate
{
	/**
	 * nom du groupe
	 *
	 * @private string
	 */
	public $groupName;
	/**
	 * mot de pass 
	 *
	 * @private string
	 */
	public $mdpData;
	private $user=array();
	private $right;
	
	public function __construct()
	{
		echo 'class: '.__CLASS__.'methode :'.__METHOD__.'<br/>';
	} 
	
	/**
	 * inplemente un groupe
	 *
	 * @param array $data
	 */
	public function setGroupe($data)
	{
		$this->groupName=$data['groupname'];
		$this->mdpData=$data['mdp_data'];
	}
	
	public function getGroupe()
	{
		return array('groupname'=>$this->groupName,'mdpData'=>$this->mdpData);
	}
	

	public function addUser(Users $user,$key)
	{
		$this->user[$key]=$user;
	}
	
	public function getIterator()
	{
		$iterator= new UserIterator($this->user);
		return $iterator;
	}
		
	public function isAuth($data)
	{
		if($data===1)
			$this->right=true;
		else 
			$this->right=false;
		return $this->right;
	}
	
	public function newGroupe()
	{
		
	}
	
	public function deleteGroupe()
	{
		
	}

	public function modifyGroupe()
	{
		
	}
	
	public function __destruct()
	{
		unset($this->groupName);
		unset($this->mdpData);
		echo 'class: '.__CLASS__.'methode :'.__METHOD__.'<br/>';
	}
}
et l'implementation
$mysql=new Mysqldb(SERVEUR,LOGIN,PASS,BASE);
$dao=new DAO($mysql);
$groupe=new Groupe();
$use=new Users();
$param=array('g.groupname="internaut"');
$tab=$dao->getGroupData($param);
//print_r($tab);
if($tab)
{
	foreach ($tab as $cle0=>$val0)
	{
		$groupe->setGroupe($val0);
		$tab1=$dao->getUserData(array('g.groupname="'.$val0['groupname'].'"'));
		if($tab1)
		{
			foreach ($tab1 as $cle=>$val1)
			{
				echo 'cle: '.$cle0.' valeur=>'.print_r($val0).'<br/>';
				echo 'cle: '.$cle.' valeur=>'.print_r($val1).'<br/>';
				$use->setUser($val1);
				$use->setGroupeUser($groupe);
				$groupe->addUser($use,$cle);
				//print_r($groupe);
			}
			
		}
		/*$use->setUser(array('login'=>'jeff','mdp'=>'motDePasse'));
		$use->setGroupeUser($groupe);*/
		//$groupe->addUser($use,0);
	}
	
}
else 
	echo 'pas de groupe<br/>';
echo '<pre>';
echo var_dump($groupe).'</pre>';
tant que j'ai un seul user ca va mais si j'en ai deux, le premier n'est pas recuperer et le deuxieme se repete 2 fois
une histoire de boucle?non car les 2 user sont afficher une seul fois
une histoire de reference?non je crois pas, mais peut etre il faudrai cloner l'objet??
:?

et c'est pas facile d'y voit quelque chose avec les reference croisé[/code]

Posté : 20 nov. 2005, 17:39
par jeff
petite correction et ca marche beaucoup mieux
class Users
{
	private $login;
	private $mdp;
	private $auth;
	private $groupe;
	
	public function __construct()
	{	
		echo 'class: '.__CLASS__.'methode :'.__METHOD__.'<br/>';	
	}
	
	public function setUser($data)
	{
		$this->login=$data['login'];
		$this->mdp=$data['mdp'];
	}
	
	public function setGroupeUser(Groupe $data)
	{
		$this->groupe=$data;
	}
	
	public  function  getUser()
	{
		return $this;
	}
	
	public function getUsertoGroupe()
	{
		return array($this->login,$this->mdp);
	}
	
	
	public function __destruct()
	{
		echo 'class: '.__CLASS__.'methode :'.__METHOD__.'<br/>';
	}
}

class Groupe implements IteratorAggregate
{
	/**
	 * nom du groupe
	 *
	 * @private string
	 */
	public $groupName;
	/**
	 * mot de pass 
	 *
	 * @private string
	 */
	public $mdpData;
	private $user=array();
	private $right;
	
	public function __construct()
	{
		echo 'class: '.__CLASS__.'methode :'.__METHOD__.'<br/>';
	} 
	
	/**
	 * inplemente un groupe
	 *
	 * @param array $data
	 */
	public function setGroupe($data)
	{
		$this->groupName=$data['groupname'];
		$this->mdpData=$data['mdp_data'];
	}
	
	public function getGroupe()
	{
		return array('groupname'=>$this->groupName,'mdpData'=>$this->mdpData);
	}
	

	public function addUser($user,$key)
	{
		$this->user[$key]=$user;
	}
	
	public function getIterator()
	{
		$iterator= new UserIterator($this->user);
		return $iterator;
	}
		
	public function isAuth($data)
	{
		if($data===1)
			$this->right=true;
		else 
			$this->right=false;
		return $this->right;
	}
	
	public function newGroupe()
	{
		
	}
	
	public function deleteGroupe()
	{
		
	}

	public function modifyGroupe()
	{
		
	}
	
	public function __destruct()
	{
		unset($this->groupName);
		unset($this->mdpData);
		echo 'class: '.__CLASS__.'methode :'.__METHOD__.'<br/>';
	}
}
$mysql=new Mysqldb(SERVEUR,LOGIN,PASS,BASE);
$dao=new DAO($mysql);
$groupe=new Groupe();
$use=new Users();
$param=array('g.groupname="internaut"');
$tab=$dao->getGroupData($param);
//print_r($tab);
if($tab)
{
	foreach ($tab as $cle0=>$val0)
	{
		$groupe->setGroupe($val0);
		$tab1=$dao->getUserData(array('g.groupname="'.$val0['groupname'].'"'));
		if($tab1)
		{
			foreach ($tab1 as $cle=>$val1)
			{
				echo 'cle: '.$cle0.' valeur=>'.print_r($val0).'<br/>';
				echo 'cle: '.$cle.' valeur=>'.print_r($val1).'<br/>';
				$use->setUser($val1);
				$use->setGroupeUser($groupe);
				$groupe->addUser($use->getUsertoGroupe(),$cle);
				//print_r($groupe);
			}
			
		}
		/*$use->setUser(array('login'=>'jeff','mdp'=>'motDePasse'));
		$use->setGroupeUser($groupe);*/
		//$groupe->addUser($use,0);
	}
	
}
else 
	echo 'pas de groupe<br/>';
echo '<pre>';
echo var_dump($groupe).'</pre>';


foreach ($groupe as $val)
{
	print_r($val);
}
bon ca fonctionne un peu pres mais mon iterateur ne renvoi rien??
je devrai bien trouver :)

Posté : 20 nov. 2005, 19:41
par jeff
bon iterator fonctionne
pour eviter les reference croiser je n'est pas renvoyé l'objet groupe en entiers mais juste le groupname et le mdpData

heu je me pose la question suivante ( j'avais pas fait attention mais lors de ton premier poste mdpData n'apparait pas dans group)
elle serait plutot dans un objet qui ferai l'interface entre Groupe et Mysql :?: :?:

Posté : 22 nov. 2005, 13:45
par jeff
bon je reviens a la charge avec mes sessions
voici le code utiliser dans la page d'autehtification
public function auth_action()
	{ 
		$mysql= new Mysqldb(SERVEUR,LOGIN,PASS,BASE); 
		$dao= new DAO($mysql);
		$data=$dao->getUserId(array('u.login="'.$_POST['log'].'"','u.mdp="'.md5($_POST['pass']).'"'));
		if($data)
		{	
			$use=new Users();
			$grp=new Groupe();
			$use->setUser(array('login'=>$_POST['log'],'mdp'=>md5($_POST['pass'])));
			$data=$dao->getGroupData(array('u.userid='.$data));
			$grp->setGroupe($data[0]);
			$use->setGroupeUser($grp);
			$use->setAuth(true);
			$grp->addUser($use->getUsertoGroupe(),0);
			echo 'user<pre>';
			echo var_dump($use).'</pre>';
			echo 'groupe<pre><br/>';
			echo var_dump($grp).'</pre>';
			$_SESSION['grp']=$grp;
			$_SESSION['use']=$use;
			echo 'ok';	
				$this->tpl='admin/index.tpl';
				$mv=new ModelView();
				$mv->setView($this->tpl);
				return $mv;
		}
		else 
		throw new MyException('mot de passe ou login incorrecte');
	}
et les objets creer

Code : Tout sélectionner

object(Users)#6 (4) { ["login:private"]=> string(4) "jeff" ["mdp:private"]=> string(32) "3c0cb28aebfb711a03eb2c1e5830e0b9" ["auth:private"]=> bool(true) ["groupe:private"]=> object(Groupe)#7 (3) { ["groupName:private"]=> string(10) "ad_general" ["mdpData:private"]=> string(16) "2KrrJWBB7GBuSPVQ" ["user"]=> array(1) { [0]=> array(4) { ["login"]=> string(4) "jeff" ["mdp"]=> string(32) "3c0cb28aebfb711a03eb2c1e5830e0b9" ["groupe"]=> string(10) "ad_general" ["mdpData"]=> string(16) "2KrrJWBB7GBuSPVQ" } } } } groupe object(Groupe)#7 (3) { ["groupName:private"]=> string(10) "ad_general" ["mdpData:private"]=> string(16) "2KrrJWBB7GBuSPVQ" ["user"]=> array(1) { [0]=> array(4) { ["login"]=> string(4) "jeff" ["mdp"]=> string(32) "3c0cb28aebfb711a03eb2c1e5830e0b9" ["groupe"]=> string(10) "ad_general" ["mdpData"]=> string(16) "2KrrJWBB7GBuSPVQ" } } }
donc les objets sont crées, remplis et mis en sesseion

voici la page ou je recupere les sessions
	var_dump($_SESSION['grp']);
	print_r($_SESSION['grp']->getGroupe());
	print_r($_SESSION['use']->getUser());
	/*foreach ($_SESSION['grp'] as $groupe)
	{
		print_r($groupe);
		echo $groupe['login'];
	}*/
	if($_SESSION['use']->getAuth()===true)
	{
et voici la tete des objet mis en sessions

Code : Tout sélectionner

object(Groupe)#2 (3) { ["groupName:private"]=> NULL ["mdpData:private"]=> NULL ["user"]=> array(1) { [0]=> array(4) { ["login"]=> string(4) "jeff" ["mdp"]=> string(32) "3c0cb28aebfb711a03eb2c1e5830e0b9" ["groupe"]=> string(10) "ad_general" ["mdpData"]=> string(16) "2KrrJWBB7GBuSPVQ" } } Users Object ( [login:private] => jeff [mdp:private] => 3c0cb28aebfb711a03eb2c1e5830e0b9 [auth:private] => 1 [groupe:private] => Groupe Object ( [groupName:private] => [mdpData:private] => [user] => Array ( [0] => Array ( [login] => jeff [mdp] => 3c0cb28aebfb711a03eb2c1e5830e0b9 [groupe] => ad_general [mdpData] => 2KrrJWBB7GBuSPVQ ) ) ) )
comme vous pouvez le voir l'objet user est bien en session, mais l'objet groupe n'est pas rempli a par list->user

:?:

et c'est qui super BOULET c'set moi ](*,)
je detruisait $this->groupname et $this->mdpData :D