On avait commencé ainsi, on générait le fichier php à une table grâce à un script (dans phpcompta/dev/manage-code/create-file/create-phpclass.py)
Les colonnes de la table sont dans un tableau et déclaré comme variable privée. Ce point est important. Cela oblige à utiliser les setters/getters. Cela vous permet aussi de faire correspondre des noms parlants à des noms de colonnes parfois hmm… moins parlants.
Cependant, je préfère souvent utiliser les commandes SQL plutôt que de passer par les objets. D'abord pour des raisons de performance, d'utilisation de la mémoire… La théorie qui veut que l'application doit être indépendante de la base de données n'est pas un mauvais principe mais dans la vie réelle, il est rare que l 'on change le programme de base de données pour un autre.
class Todo_List { private static $variable=array( "id"=>"tl_id", "date"=>"tl_date", "title"=>"tl_title", "desc"=>"tl_desc", "owner"=>"use_login"); private $cn; private $tl_id,$tl_date,$tl_title,$use_login; function __construct ($p_init) { $this->cn=$p_init; $this->tl_id=0; $this->tl_desc=""; $this->use_login=$_SESSION['g_user']; }
Ici voici, des setters / getters génériques, ce qui permet de ne pas en avoir un par variable. Ce qui est bien pratique. On accède aux données avec set_parameter ('date','01.01.2009') ou avec get_parameter ('date');
public function get_parameter($p_string) { if ( array_key_exists($p_string,self::$variable) ) { $idx=self::$variable[$p_string]; return $this->$idx; } else exit (__FILE__.":".__LINE__.'Erreur attribut inexistant'); } public function set_parameter($p_string,$p_value) { if ( array_key_exists($p_string,self::$variable) ) { $idx=self::$variable[$p_string]; if ($this->check($idx,$p_value) == true ) $this->$idx=$p_value; } else exit (__FILE__.":".__LINE__.'Erreur attribut inexistant'); }
Ceci est la fonction qui contrôle que les données sont valides. Cela pourrait aussi être fait dans la base de données, soit avec des contrôles d'intégrités (foreign key, primary key) soit avec des procédures SQL embarquées de contrôle.
public function check($p_idx,&$p_value) { if ( strcmp ($p_idx, 'tl_id') == 0 ) { if ( strlen($p_value) > 6 || isNumber ($p_value) == false) return false;} if ( strcmp ($p_idx, 'tl_date') == 0 ) { if ( strlen(trim($p_value)) ==0 ||strlen($p_value) > 12 || isDate ($p_value) == false) return false;} if ( strcmp ($p_idx, 'tl_title') == 0 ) { $p_value=substr($p_value,0,120) ; return true; } if ( strcmp ($p_idx, 'tl_desc') == 0 ) { $p_value=substr($p_value,0,400) ; return true;} return true; }
Enfin la fonction save, qui permet soit d'ajouter soit de même à jour. Évidemment on utilisera des requêtes SQL Prepare, afin d'éviter les problèmes de guillemets et donc d'injection SQL.
public function save() { if ( $this->get_parameter("id") == 0 ) $this->insert(); else $this->update(); } public function insert() { if ( $this->verify() != 0 ) return; $sql="insert into todo_list (tl_date,tl_title,tl_desc,use_login) ". " values (to_date($1,'DD.MM.YYYY'),$2,$3,$4) returning tl_id"; $res=ExecSqlParam($this->cn, $sql, array($this->tl_date, $this->tl_title, $this->tl_desc, $this->use_login) ); $this->tl_id=pg_fetch_result($res,0,0); } public function update() { if ( $this->verify() != 0 ) return; $sql="update todo_list set tl_title=$1,tl_date=to_date($2,'DD.MM.YYYY'),tl_desc=$3 ". " where tl_id = $4"; $res=ExecSqlParam($this->cn, $sql, array($this->tl_title, $this->tl_date, $this->tl_desc, $this->tl_id) ); }
Comme cette partie est vraiment répétitive et change peu, j'ai mis au point un script (dev/manage-code/create-file/create_phpclass.py) pour directement générer le code sur base de la définition d'une table. Cela réduit vraiment le temps de travail.
static function test_me() { $cn=DbConnect(dossier::id()); $r=new Todo_List($cn); $r->set_parameter('title','test'); $r->use_login='phpcompta'; $r->set_parameter('date','02.03.2008'); $r->save(); $r->set_parameter('id',3); $r->load(); print_r($r); $r->set_parameter('title','Test UPDATE'); $r->save(); print_r($r); $r->set_parameter('id',1); $r->delete(); } public function get_info() { return var_export(self::$variable,true); }