Location: PHPKode > scripts > Simple Abstract Table > simple-abstract-table/table.abstract.php
<?php

///////////////////////////////////////////////////////////////////////////////////////////////////
// Classe: Table abstraite
// Auteur: Emilien Dreyfus (hide@address.com)
// Projet: Kobua
//
// Cette classe permet de faire abstraction d'une table de base mysql
// Elle contruit un objet unique ou multiple à partir d'une requete,
// permet d'itérer les éléments et de les sauvegarder.
// 
// Utilisation:
//
//	-Dériver la classe et surcharger la méthode table_name() qui dois renvoyer le nom de la table
//	-Si la clef primaire est différente de id, surcharger la méthode table_primary_key() et 
//   renvoyer la clef sans fioritures.
//
//	-Instancier un objet de la classe dérivée
//	-Charger des données: 	load_from_id($id);					// Objet unique
//							load_from_where_condition($where);	// Clause WHERE mysql
//							load_all_order_by($order);			// Clause ORDER BY (Pas de where)
//							load_all();							// Charge tout les éléments
//   ou inserer un élément: set_champ1($c); puis save();
//
//  -Si données chargées, afficher ou modifier les données avec get_champ1() et set_champ1($c), 
//	 les méthodes sont crées automatiquement à la volée en fonction de la structure de la table.
//
//  -Sauvegarder avec update() si vous avez modifié un élément déja chargé avec set_
//  -Itérer avec has_next et next() de cette manière:
//
//		while($o->has_next()){
//			echo $o->get_id();
//			$o->next();
//		}
//


abstract class table{

	//Cette méthode dois etre surchargée et renvoyer le nom de la table
	protected abstract function table_name();
	
	//Cette méthode dois être sur surchargée si la clé primaire est différente de id
	protected function table_primary_key(){
		return "id";
	}
	
	
	//Flag qui permet d'interdire l'acces a une classe non instanciée
	protected $instanciated=false;
	
	//Stockage de la requete en cas d'objet multiligne
	private $multi_row_req=null;
	
	//Nombre de ligne effectives
	private $multi_row_number=0;
	
	//Compteur pour la ligne courante
	private $row_iterator_counter=0;
	
	//Valeurs modifiées par un set (tableau assoc)
	private $updated=Array();
	
	//Valeurs accessibles par les get et set
	private $values=Array();
	
	//Charge l'objet à partir d'une valeur de clef primaire
	public function load_from_id($id){
		$sql="SELECT * FROM `{$this->table_name()}` WHERE `{$this->table_primary_key()}`='$id' LIMIT 1";
			
		$req=mysql_query($sql) or die(mysql_error());
		
		if(mysql_error()==""){
			$data=mysql_fetch_assoc($req);
			$this->multi_row_number=1;
			$this->apply_data($data);
		
			return true;
		}
		return false;
		
		
	}
	
	function reset_iterator(){
		ECHO $this->multi_row_req;
		if($this->instanciated){
			mysql_data_seek ( $this->multi_row_req , 1 );
			$this->row_iterator_counter=0;
		}
		 
	}
	
	function get_num_rows(){
		return $this->multi_row_number;
	}
	
	//Charge l'objet avec une condition WHERE (Ex: id='2' ORDER BY date)
	public function load_from_where_condition($where_condition){
		$sql="SELECT * FROM ".$this->table_name()." WHERE $where_condition";

		$req=mysql_query($sql);
		
		
		if(mysql_error()==""){
			$nb=mysql_num_rows($req);
			$this->multi_row_number=mysql_num_rows($req);
			$this->multi_row_req=$req;
			$data=mysql_fetch_assoc($req);
			$this->apply_data($data);
			return true;
		}
		
		return false;
	}
	
	function delete_where_condition($where_condition){
		$sql="DELETE FROM ".$this->table_name()." WHERE $where_condition";
		$req=mysql_query($sql);
		
	}
	
	//Charge l'objet avec tous les éléments dans l'ordre spécifié (Ex: date)
	public function load_all_order_by($order){
		$sql="SELECT * FROM ".$this->table_name()." WHERE 1 ORDER BY $order";
		$req=mysql_query($sql);
		
		if(mysql_error()==""){
			$nb=mysql_num_rows($req);
		
			$this->multi_row_number=mysql_num_rows($req);
			$this->multi_row_req=$req;
			
			$data=mysql_fetch_assoc($req);
			$this->apply_data($data);
			return true;
		}
		
		return false;
	}
	
	//Charge l'objet avec toutes les lignes de la table
	public function load_all(){
		$sql="SELECT * FROM ".$this->table_name()." WHERE 1";
		$req=mysql_query($sql);
		
		if(mysql_error()==""){
			$nb=mysql_num_rows($req);
			$this->multi_row_number=mysql_num_rows($req);
			$this->multi_row_req=$req;
			$data=mysql_fetch_assoc($req);
			$this->apply_data($data);
			return true;
		}
		
		return false;
	}
	
	
	//Charge l'objet avec la prochaine ligne 
	public function next(){
		if($this->has_next()){
			if(!$this->is_last()){
				$data=mysql_fetch_assoc($this->multi_row_req);
				$this->apply_data($data);
			}
			$this->row_iterator_counter++;
			return true;
		}
	}
	function is_instanciated(){
		return $this->instanciated;
	}
	
	function reset(){
		$this->instanciated=false;
	}
	// Permet d'utiliser l'objet comme un itérateur
	//
	//	while($o->has_next()){
	//		echo $o->get_id();
	//		$o->next();
	//	}
	//
	// Le dernier has_next() retourn true mais le dernier next ne change pas l'objet.
	// Bref, utiliser la notation en exemple et ca pose pas de pb.
	
	public function has_next(){
		return ($this->instanciated && isset($this->multi_row_req) && $this->row_iterator_counter < $this->multi_row_number);
	}
	
	// Permet de savoir si c'est le dernier element
	public function is_last(){
		return ($this->row_iterator_counter == $this->multi_row_number-1);
	}
	
	//Sauvegarde les éléments modifiés de l'objet courant dans la table
	public function save(){
		if(isset($this->values[$this->table_primary_key()]) && $this->values[$this->table_primary_key()]!=""){
			$sql="UPDATE `".$this->table_name()."` SET ";
			
			foreach($this->updated as $k=>$v){
				if($v==true){
					if($this->values[$k]=="NOW()")
						$sql.="`$k`= ".$this->values[$k].",";
					else $sql.="`$k`='".$this->values[$k]."',";
					$this->updated[$k]=false;
				}
			}
			$sql=substr($sql,0,count($sql)-2);
			$sql.=" WHERE `{$this->table_primary_key()}`='{$this->values[$this->table_primary_key()]}'";
			mysql_query($sql) or die(mysql_error());
		}else if(!$this->instanciated){
			$sql="INSERT INTO `".$this->table_name()."` (";
			foreach($this->updated as $k=>$v){
				if($v==true){
					$sql.="`$k`,";
					
				}
			}
			$sql=substr($sql,0,count($sql)-2);
			$sql.=") VALUES (";
			foreach($this->values as $k=>$v){
				if($this->updated[$k]==true){
					if($v=="NOW()")
						$sql.=" $v ,";
					else
					$sql.="'$v',";
					$this->updated[$k]=false;
				}
			}
			$sql=substr($sql,0,count($sql)-2);
			$sql.=")";
			mysql_query($sql);
			$this->instanciated=true;
			return mysql_error()=="";
		}else throw new Exception("Erreur dans save");
	}
	
	function insert(){
		if(!$this->instanciated){
			$sql="INSERT INTO `".$this->table_name()."` (";
			foreach($this->updated as $k=>$v){
				if($v==true){
					$sql.="`$k`,";
					
				}
			}
			$sql=substr($sql,0,count($sql)-2);
			$sql.=") VALUES (";
			foreach($this->values as $k=>$v){
				if($this->updated[$k]==true){
					if($v=="NOW()")
						$sql.=" $v ,";
					else
					$sql.="'$v',";
					$this->updated[$k]=false;
				}
			}
			$sql=substr($sql,0,count($sql)-2);
			$sql.=")";
			mysql_query($sql);
			$this->instanciated=true;
			return mysql_error()=="";
		}else throw new Exception("Erreur dans insert");
	}
	
	
	//Supprime l'objet courant dans la table
	public function delete(){
		$sql="DELETE FROM`".$this->table_name()."` WHERE `{$this->table_primary_key()}`='{$this->values[$this->table_primary_key()]}' LIMIT 1";
		mysql_query($sql) or die($sql." ".mysql_error());
	}
	
	
	// Interception des accesseurs. 
    public function __call($method, $attrs) {
    
   
         $prefix  = substr($method, 0, 4);
         $suffix  = substr($method,4,strlen($method)-4);
         $cattrs  = count($attrs);
        
        	
         if ($prefix == 'set_' && $cattrs == 1) {
           	$this->updated[$suffix]=true;
          
            return $this->values[$suffix]=$attrs[0];
         }
             
         if($this->instanciated){
          	if ($prefix == 'get_' && $cattrs == 0) {
           		if(isset($this->values[$suffix]))
               		return $this->values[$suffix];
               	else throw new Exception("Champ $suffix inexistant");
           	}
         }else {       
         	return "";
     	 }
             
         throw new Exception("La méthode $method n'existe pas");
    
    }
    
	//Effectue le chargement des données dans la classe (apres requete)
	private function apply_data($data){
		if(is_array($data)){
			foreach($data as $k=>$v){
					$this->values[$k]=$v;
					$this->updated[$k]=false;
			}
			$this->instanciated=true;
		}
	}
}
?>
Return current item: Simple Abstract Table