Cache et factory

Petit nouveau ! | 4 Messages

24 juil. 2009, 13:48

Bonjour j'ai créé une classe pour gérer des "Items" (User, Message etc...). L'Item peut être soit charger depuis la base de donnée soit depuis le Cache.


Ici la classe de base Item
<?php 
class Item{
		protected $id;
		protected $log;
		protected $db;
		
		public function __construct($id){
			$this->log=Log::getInstance();
			$this->db = MySQLDataBase::getInstance();
			$this->log->Trace('Item::__construct');
			if($id!=NULL){
				$this->id=$id;
			}else $this->id=NULL;
		}
		
		public function getId(){
			return $this->id;
		}

		public function setId($value){
			$this->log->Trace('Item::setId - value :'.$value);
			$this->id=$value;
		}
		
		protected function saveToCache(){
			if($this->id!=NULL){				
				$cache=new Cache(get_class($this), $this->id);
				$cache->set($this);
			}
		}
		
		public function Load(){
			$this->log->Trace('Item::Load');
			$this->log->Trace('Not implemented');
		}
		
		public function WakeUpFromCache(){
			$this->db=MySQLDataBase::getInstance();
			$this->log=Log::getInstance();
		}
		
		public function __destruct() {
			$this->prepareToSleep();
			$this->saveToCache();
		}
		
		public function Free(){
			$this->__destruct();
		}
		
		public function prepareToSleep(){
			$this->db=NULL; //can't be serialized, cause Fatal error: Exception thrown without a stack frame in Unknown on line 0
			$this->log=NULL;		
		}
	}
?>
Ici ItemFactory
<?php
	class ItemFactory{
		private $log;
		public function __construct(){
			$this->log = Log::getInstance();
		}
		
		public function get($type, $id){
			$this->log->Trace('ItemFactory::get');
			if($id==NULL) $item = $this->getNew($type, $id);
			else{
				$cache=new Cache($type, $id);
				if($cache->getTime() > 60*60){
					$item = $this->Load($type, $id);
				}else{
					$item=$cache->get();
					$item->WakeUpFromCache();
				}				
			}	
			return $item;
		}
		
		private function Load($type, $id){
			$this->log->Trace('ItemFactory::Load');			
			$item = $this->getNew($type, $id);
			$item->Load();
			return $item;
		}
		
		private function getNew($type, $id){
			$this->log->Trace('ItemFactory::getNew');
			$this->log->Trace($type);
			return new $type($id);
		}
	}
?>
Et voilà un petit exemple
<?php
	$factory = new ItemFactory();
	//je charge un user depuis ma db ou le cache
	$user = $factory->get('User', $my_id);
	echo $user->getName();
	//je veux crer un nouveau message
	$message = $factory->get('Message', NULL);
	$message->setUser($user);
	$message->setTime(time());
	$message->setContent('My message');
	$message->Save();
?>
Qu'en pensez vous ?

Eléphant du PHP | 111 Messages

24 juil. 2009, 14:09

L'idée, c'est de gérer un user comme on gère un log, comme on gère une connexion, comme on gère une voiture ?

Je ne suis pas sûr d'avoir compris ce que tu entends par Item ...

Petit nouveau ! | 4 Messages

24 juil. 2009, 14:19

En fait chaque "Item" est une entrée unique dans la BDD.

L'idée c'etait de simplifier les requêtes SQL et d'en faire moins pour des choses qui reviennent souvent.

Par exemple pour afficher l'utilisateur, il sera loader une fois depuis la bdd ensuite on le recuperera depuis le cache, pareil pour les messages etc...

Le seul défaut, c'est les collections d'Item. Si je load par exemple tous les messages entre tel date et tel date ça va être "long" si la plupart n'ont jamais été chargés.

Pour les logs et les connexion ou se genre de trucs c'est des classes à part qui n'ont rien à voire.

Pour gérer la connexion d'un utilisateur j'ai une classe IdentityManager qui gère sa session, la connection ce genre de truc. User ou message c'est juste le reflet de la base de donnée avec quelques méthodes liés à la nature de l'Item (sendMail par exemple).

PS : Je sais pas si mon code à une utilisation concréte utile, je suis étudiant, je voulais juste faire un système de cache ^^.

Eléphant du PHP | 111 Messages

24 juil. 2009, 14:29

Pour gérer tes items tous de la même manière, tourne toi vers un modèle en meta données.

Pour le fonctionnement du cache, il y en a deux types : persistant (fichier) et non persistant (en mémoire).

Pour le fonctionnement du cache lui même :
http://www.siteduzero.com/tutoriel-3-31 ... e-php.html

Petit nouveau ! | 4 Messages

24 juil. 2009, 14:42

J4ai déjà codé un cache de type persistant.

Pour le truc des métadonnéees. Plutôt que de coder une classe par Item je fais un fichier xml du genre :

Code : Tout sélectionner

<Item name="User"> <attribute name="Id" type="Integer"/> <attribute name="Name" type="String"/> [...] <method name="sendMail" function="f_user_send_mail" /> [...] </Item>
C'est bien ça ?

Edit : le code du cache
<?php
	class Cache{
		private $name;
		//private $log;
		
		public function __construct($strObjectType, $strId){
			//$this->log=Log::getInstance();
			$this->name=$strObjectType.'-'.$strId;//to be competed with address
			$this->name=Address::CACHE.$this->name;
			$this->name=sha1($this->name);
			//$this->log->Trace('Cache::__construct - '.$strObjectType.' - '.$strId);
			//$this->log->Trace('Cache::__construct - '.$this->name);
		}
		
		public function get(){
			//$this->log->Trace('Cache::get');
			$file = new File($this->name, 'r+');
			$strObject="";
			$temp="";
			do{
				$temp=$file->Read();
				$strObject.=$temp;
			}while($temp!=NULL);
			
			$object=unserialize(base64_decode($strObject));
			return $object;
		}
		
		public function set($object){
			//$this->log->Trace('Cache::set');
			$strObject=base64_encode(serialize($object));
			$file = new File($this->name, 'w+');
			$file->Write($strObject);
		}	

		public function getTime(){
			$file = new File($this->name, 'r');
			return time()-$file->getLastEdit();
		}
	}
?>
C'est un peu different par rapport à ton lien, je ne met pas en cache une page mais des objets en utilisant serialize et unserialize.

Eléphant du PHP | 111 Messages

24 juil. 2009, 15:11

Les meta données, c'est une manière de travailler en SQL ^^. Un peu compliqué à prendre en main, très gourmand, et nécessite un système de cache très au point. Ultra modulable, par contre.

Y'a un article sur developpez.com, à ce sujet, qui manque de certaines bases, mais assez complet dans l'ensemble.

Sinon, pour apprendre, ton système de cache est pas mal.

Tu peux lire la doc de Hoa aussi, projet développé par Ivan Enderlain, qui est sur ce forum sous le nom de Hywan. J'ai parcouru rapidement la partie cache, et c'était plutôt bien fait.

http://hoa-project.net/Manuel/Reference/Hoa_Cache.html

Mammouth du PHP | 965 Messages

24 juil. 2009, 15:16

Les meta données, c'est une manière de travailler en SQL ^^. Un peu compliqué à prendre en main, très gourmand, et nécessite un système de cache très au point. Ultra modulable, par contre.

Y'a un article sur developpez.com, à ce sujet, qui manque de certaines bases, mais assez complet dans l'ensemble.

Sinon, pour apprendre, ton système de cache est pas mal.

Tu peux lire la doc de Hoa aussi, projet développé par Ivan Enderlain, qui est sur ce forum sous le nom de Hywan. J'ai parcouru rapidement la partie cache, et c'était plutôt bien fait.

http://hoa-project.net/Manuel/Reference/Hoa_Cache.html
<hs>

Comment qu'il fait de la lèche à Hywan :!:

</hs>

Petit nouveau ! | 4 Messages

24 juil. 2009, 15:22

Je vais m'inspirer de Hoa pour apporter quelques améliorations.

Merci beaucoup.

Eléphant du PHP | 111 Messages

24 juil. 2009, 15:24

Hu hu.

Le peu d'admins avec qui j'ai des contacts ici te dira que je n'essaie pas de faire de la lèche ^^.

Je pense vraiment que le système de cache de Hywan est un bon système (hop, re une dose).

ViPHP
ViPHP | 4674 Messages

26 juil. 2009, 20:31

Hey :-),

On dit "Enderlin" et pas "Enderlain" ;-).
Hoa_Cache est pas mal mais il peut être amélioré. On peut faire plus simlpe. Ce que tu peux regarder par contre, c'est toute la partie backend. Ça, ça peut t'intéresser.
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).