Page 1 sur 1

Aide pour conception de classes

Posté : 17 janv. 2011, 01:32
par BafS
Bonjour à tous !

Je suis en train de créer une sorte de petit CMS en POO.

J'ai pour le moment j'ai les classes :
  • Database : Pour la sauvegarde/récupération de données. Je l'ai mise en "static" pour pouvoir l’appeler partout (bonne idée ?).
    Article : Pour lire les articles dans la base de données, en écrire un nouveau etc...
    Member : Pour se loger, s'inscrire etc...
Lorsqu'on se log, cela instancie la classe Member puis créer une variable $_SESSION qui contient l'objet de la classe Member (pour éviter d'instancier chaque fois Member).
Dans ma classe Article j'ai une methode setArticle() qui enregistre (entre autres) le nom de l’auteur. Pour cela j'utilise (dans la classe) $_SESSION['login']->login plutôt que d'instancier la classe Member et avoir le nom du membre. Le problème c'est qu'en utilisant les SESSIONs ma classe est beaucoup moins indépendante et l'utiliser dans un autre projet deviendrait compliqué mais instancier la classe Member me parait beaucoup moins optimisé (mais plus propre?).
L'autre idée était d'utiliser l’héritage en faisant une super-classe "CMS" (par ex.) mais cela me semble absolument mauvais du point de vue de la conception.

Pourriez vous m'éclairer sur ces points s'il vous-plaît. Peut être utilise-je mal la POO.

Une dernière chose. Si, par la suite, je voudrais pouvoir modifier un menu, cela vaut-il la peine de faire une classe "Menu" ou faudrait-il mieux faire une classe "Options" avec les méthodes pour modifier le menu ?

Merci beaucoup d'avance et excusez moi si certaines questions peuvent sembler trop triviales.

Cordialement

BafS

Re: Aide pour conception de classes

Posté : 17 janv. 2011, 01:49
par stealth35
Hello, utiliser la session est une bonne solution, surtout pour se genre d'info, t'as classe n'en est pas pour autant dépendante puisque qu'elle sert uniquement en socket les infos de l'utilisateur connecter.
Par contre je pense pas qu'un classe mère CMS sois une bonne idée, faut essayé un maximum de travailler en block, comme pour ton menu, ou finalement ton layout final c'est un ensemble de block html
Si tu veux montre un peu de code :wink:

Re: Aide pour conception de classes

Posté : 17 janv. 2011, 02:08
par BafS
Ok, merci pour tes infos. Alors voici un peu de code.

La classe Database
<?php
final class Database
{
	private static $dataBasePath = 'db/';
	private static $protectedLine = '<?php exit();?>';
	
	public static function get($fileName, $fileType = 'txt') {
		$path = (self::$dataBasePath).$fileName.'.'.$fileType;
		if(file_exists($path))
			return file_get_contents($path);
		else
			return false;
	}
	
	public function set($fileName, $rawData, $fileType = 'txt') {
		file_put_contents((self::$dataBasePath).$fileName.'.'.$fileType, $rawData);
		//return true;
	}
	
	public static function getProtected($fileName) {
		$path = (self::$dataBasePath).$fileName.'.php';
		if(file_exists($path)) {
			$raw = file_get_contents($path);
			$raw = str_replace(self::$protectedLine.PHP_EOL, '', $raw);
			return $raw;
		} else {
			return false;
		}
	}
	
	public function setProtected($fileName, $rawData) {
		$fp = fopen((self::$dataBasePath).$fileName.'.php', 'w+');
		fwrite($fp, self::$protectedLine.PHP_EOL);
		fwrite($fp, $rawData);
		fclose($fp);

	}
}
classe Article
<?php
class Article
{
	private $articleName;
	private $articleDir = 'articles';
	
    public function __construct($articleName = null) {
		$this->articleName = $articleName;
	}
	
	private function getArticleFileName($articleName) {
		//TODO ex : "J'aime noël !" -> "j_aime_noel__"
		$articleFileName = strtolower($articleName);
		$articleFileName = str_replace(' ', '_', $articleFileName);
		return $articleFileName;
	}
	
	public function getArticle($articleName = null) {
		$articleName = empty($articleName) ? ($this->articleName) : ($this->articleName = $articleName);
		$articleContent = DataBase::get(($this->articleDir).'/'.$articleName);
		return unserialize($articleContent);
	}
	
	public function setArticle($articleName, $articleContent, $option = null) {
		$article['name'] = $articleName;
		$article['content'] = $articleContent;
		$article['author'] = $_SESSION['login']->login;
		//$article['author'] = $author;
		$article['date_last'] = date('d-m-y|H:i');
		$article['option'] = $option;
		
		$articleFileName = $this->getArticleFileName($articleName);
		
		$articleRaw = serialize($article);
		Database::set(($this->articleDir).'/'.$articleFileName, $articleRaw);
	}
}
Et la classe Member
<?php
///todo : catch...try
class Member
{
	public $logged;
	public $login;	
	
	private $memberDir = 'members';
	private $dateFormat = 'd-m-y|H:i';
	private $salt = '?²#-';
	
	public function __construct($login = '')
	{
		if(isset($_SESSION['login']) && strlen($_SESSION['login'])>0) {
			$this->logged = true;
			$this->login = $login;
		}
	}
	
	//To login
	public function login($login, $password = null)
	{
		$path = $this->memberDir.'/members';
		$raw = (DataBase::getProtected($path));
		$members = unserialize($raw);
		
		if(@$members[$login]==$this->hash($password) || $this->logged)
		{
			$this->logged = true;
			$this->login = $login;
			$this->setMemberOption('lastCo', date($this->dateFormat));
			return true;
		} else {
			echo "{DEBUG:not login}";//DEBUG
			//catch error
			return false;
		}
	}
	
	//Get Member Option (lang, flag...)
	public function getMemberOption($option) { //Heritage:masquage pour admin -> ($option, $login)
		if($this->logged) {
			$path = $this->memberDir.'/'.$this->login;
			$data = unserialize(DataBase::getProtected($path));
			return $data[$option];
		} else {
			return false;
		}
	}
	
	public function setMemberOption($option, $value) {
		if($this->logged) {
			$path = $this->memberDir.'/'.$this->login;
			$data = unserialize(DataBase::getProtected($path));
			$data[$option] = $value;
			DataBase::setProtected($path, serialize($data));
			return true;
		} else {
			return false;
		}
	}
	
	//return the hash of plain text
	private function hash($plain)
	{
		return md5($this->salt.md5($plain));
	}
	
	//create new member (if not exist)
	//TODO:admin only (flag 'a')
	public function newMember($login, $password, $flag = 1, $lang = 'en')
	{
		$path = $this->memberDir.'/members';
		$raw = (DataBase::get($path));
		$members = unserialize($raw);
		
		if(!file_exists($path) || !in_array($login, $members))
		{
			$members[$login] = $this->hash($password);
			DataBase::setProtected($path, serialize($members));
			
			/* Options */
			$path = $this->memberDir.'/'.$login;
			$data = array();
			$data['lang'] = $lang;
			$data['lastCo'] = '';
			$data['flag'] = $flag;
			DataBase::setProtected($path, serialize($data));
			
			return true;
		} else {
			//error
			return false;
		}
	}
}
Puis plutôt que t'utiliser l’héritage et faire une classe Admin j'utilise un système de "flags" (un peut comme le chmod) comme ça c'est plus simple si je veux ajouter un niveau par la suite (ex: utilisateur, modérateur, admin, super-admin).

Merci !

PS: Oui, je n'utilise pas de SRGB mais je fais tout en serialize :)

Re: Aide pour conception de classes

Posté : 17 janv. 2011, 02:23
par momox
Pour ton système de gestion des droits, peut être qu'une classe "acl" (access control list) serait utile, afin de pouvoir gérer plus finement les rôles de chacun, administrateur, super-modérateur, modérateur et modérateur n'étant que des "modéles" de permissions distincts, isnt'it ?

Re: Aide pour conception de classes

Posté : 17 janv. 2011, 02:44
par BafS
Pour ton système de gestion des droits, peut être qu'une classe "acl" (access control list) serait utile, afin de pouvoir gérer plus finement les rôles de chacun, administrateur, super-modérateur, modérateur et modérateur n'étant que des "modéles" de permissions distincts, isnt'it ?
J'ai jamais fait ça mais je vois plus ou moins l'idée. C'est d'ajouter chaque droit indépendamment pour chaque utilisateur (par ex. lecteur, editeur, moderateur) ? Merci !

Re: Aide pour conception de classes

Posté : 17 janv. 2011, 10:53
par stealth35
Pour ton système de gestion des droits, peut être qu'une classe "acl" (access control list) serait utile, afin de pouvoir gérer plus finement les rôles de chacun, administrateur, super-modérateur, modérateur et modérateur n'étant que des "modéles" de permissions distincts, isnt'it ?
J'ai jamais fait ça mais je vois plus ou moins l'idée. C'est d'ajouter chaque droit indépendamment pour chaque utilisateur (par ex. lecteur, editeur, moderateur) ? Merci !
et chaque utilisateur a des droits dans les classes (ou plutôt les actions), par exemple un lecteur peu avoir accès a getArticle, mais pas setArticle, un rédacteur oui

Re: Aide pour conception de classes

Posté : 17 janv. 2011, 12:25
par sadeq
Bonjour, voici une pseudo gestion des privilèges par héritage entre classes :
Les actions sur les articles sont réparties en sous-classes représentant des groupes de privilèges d'accès : lecteur, éditeur, ... d'articles Et les membres sont réparties par rôle : membre lecteur, éditeur, ...
Un membre lecteur issu de la sous-classe Lecteur(fille de membre) ne peut faire que les actions prévues au lecteur d'acticles dans la sous-classe LecteurArticle(fille de Article)
Un membre éditeur issu de la sous-classe Editeur(fille de membre) ne peut faire que les actions prévues à un éditeur d'articles dans la sous-classe EditeurArticle(fille de LecteurArticle et de Article)
<?php 
##################
class article 
{
	protected $titres = array( 1=>"Titre 1", 2=>"Titre 2");
}
class lecteurArticle extends article
{
	public function getTitre($id)
	{
		if (isset($this->titres[$id])) return $this->titres[$id]; else return false;
	}
}
class editeurArticle extends lecteurArticle
{
	public function setTitre($id, $titre)
	{
		if (!isset($this->titres[$id])) 
		{
			$this->titres[$id] = $titre;
			return true;
		} 
		else return false;
	}
}
##################
class membre
{
	public $nom;
	public $article;	
}
class lecteur extends membre
{
	function __construct($nom)
	{
		$this->nom = $nom;
		$this->article = new lecteurArticle();
	}

}
class editeur extends membre
{
	function __construct($nom)
	{
		$this->nom = $nom;
		$this->article = new editeurArticle();
	}
}
class administrateur extends membre
{
}
#####################

$regis = new lecteur("regis");
echo sprintf("<p>Je suis le membre %s</p>", $regis->nom);
echo sprintf("<p>Le titre n°%s est: %s</p>", 1, $regis->article->getTitre(1));

$toto = new editeur("toto");
echo sprintf("<p>Je suis le membre %s</p>", $toto->nom);
echo sprintf("<p>Ajout du Titre 3 ? (%s)</p>",$toto->article->setTitre(3, "Titre 3")?"Effectué":"Non effectué");
echo sprintf("<p>Le titre n°%s est: %s</p>", 3, $toto->article->getTitre(3));

?>

Re: Aide pour conception de classes

Posté : 19 janv. 2011, 23:52
par BafS
Merci beaucoup pour les détails, je vais me pencher sur cette classe ACL.

Et sinon pour le reste du code, cela semble correcte ? Pas de gros soucis qui vous saute aux yeux :P ?
Par exemple si je voudrais modifier le footer ou le menu ou le titre, je vais pas faire 10 methodes non ?

En tout cas, merci pour votre aide !