array ("integer", "not null", "autoincrement"), "zone"=>array ("varchar", "255", "not null"), "viewname"=>array ("varchar", "255"), "viewclients"=>array ("varchar", "255"), "comment"=>array ("varchar", "1024"), "opendate"=>array ("datetime", "not null"), "closedate"=>array ("datetime"), ); - protected $primary = "id" ; the primary key of the table (in text). Actually the dbLayer abstraction don't supports primary key on multiples columns - protected $unique = array ("column", array ("column1", "column2");) Optionnaly, you can add the - protected $debug = TRUE : enable the debug on screen (NOT FOR PROD !!) */ /** Permit abstraction on the differents SQL databases available */ class dblayer extends PDO { protected $fields = array (); protected $primary = null; protected $unique = null; protected $db = null; public $debug = FALSE; /** Return all the tables available in the database */ function listTables () { $driver = $this->getAttribute(PDO::ATTR_DRIVER_NAME); $rc = @include_once ("dbLayer".ucfirst ($driver).".php"); if ($rc === FALSE) throw new Exception (sprintf (_("dbLayer driver %s not available"), $driver), 500); } // TODO !! /** Create Table creation from $this->fields with engine abstraction Example in sqlite3 id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, in MySQL id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, */ // TODO !! /** Create automatic creation of $fields from .schema of sqlite3/ show create table `NomTable`; for MySQL SQLite3 : PRAGMA TABLE_INFO('yourtable'); MYSQL : SHOW COLUMNS FROM yourtable;*/ /** Connection to the database engine See http://fr2.php.net/manual/en/pdo.construct.php for the $dsn format */ function __construct ($dsn, $username=null, $password=null, $driver_options=null) { $this->db = new PDO ($dsn, $username, $password, $driver_options); $this->db->setAttribute (PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } /** Create a new entry in the table. Datas must be an indexed array */ function create ($datas) { if ($this->db === null) throw new Exception (_("Database not connected"), 500); if ($this->unique === null) throw new Exception (_("Unique fields of table are not defined"), 500); if (!is_array ($datas)) throw new Exception (_("The datas provided to create are not array"), 405); if (!in_array ($this->primary, $this->unique)) $this->unique[] = $this->primary; $datasOK = array (); // Check for missing parameters foreach ($this->fields as $key=>$params) { if (in_array ("autoincrement", $params)) $datas[$key] = null; if (in_array ("not null", $params) && !array_key_exists ($key, $datas)) throw new Exception ("Mandatory field '$key' not provided", 405); // TODO : Check for type inconsistancies before create $datasOK if (array_key_exists ($key, $datas)) $datasOK[$key] = $datas[$key]; } // Check if the unique constrain is valid before doing the insertion foreach ($this->unique as $columns) { if (is_array ($columns)) { $select = array (); foreach ($columns as $col) { if (!array_key_exists ($col, $datasOK)) continue; $select[] = array ($col, $datasOK[$col]); } $rc = $this->read ($select, array ($this->primary)); if (count ($rc) > 0) throw new Exception (sprintf ( _("The provided value for columns '%s' already exists"), implode (",", $columns)), 405); } else { if (!array_key_exists ($columns, $datasOK)) continue; $rc = $this->read (array (array ($columns, $datasOK[$columns])), array ($this->primary)); if (count ($rc) > 0) throw new Exception (sprintf ( _("The provided value for column '%s' already exists"), $columns), 405); } } // TODO : Check if the foreign keys constrains are valid before doing the // insertion $req = "INSERT INTO `".$this->table."` "; $req .= "(".implode (",", array_keys ($datasOK)).")"; $req .= " VALUES "; $req .= "(:".implode (",:", array_keys ($datasOK)).")"; if ($this->debug) echo "DEBUG : $req\n"; $st = $this->db->prepare ($req); foreach ($datasOK as $key=>$val) { if ($this->debug) echo "DEBUG BIND : $key->".var_export ($val, TRUE)."\n"; if ($val === null) $st->bindValue (":$key", $val, PDO::PARAM_NULL); elseif ($this->fields[$key][0] === "integer") $st->bindValue (":$key", $val, PDO::PARAM_INT); elseif ($this->fields[$key][0] === "varchar") $st->bindValue (":$key", $val, PDO::PARAM_STR); elseif ($this->fields[$key][0] === "datetime") $st->bindValue (":$key", $val, PDO::PARAM_STR); else throw new Exception ("TO BE DEVELOPPED : ".$this->fields[$key][0], 500); } $st->execute (); return $this->db->lastInsertId(); } /** Read the table content based on a select filter, ordered by order operator and the associated select value - $select = array (array ($key, $val, $operator), ...) $key=>column, $val=>value to found, $operator=>'LIKE', =... - $display = array ($col1, $col2...); Columns displayed - $order = array (array ($key, $orientation), ...) $key=>column, $orientation=ASC/DESC */ function read ($select=null, $display=null, $order=null) { if ($this->db === null) throw new Exception (_("Database not connected"), 500); if ($select !== null && !is_array ($select)) throw new Exception (_("Select information provided is not an array"), 405); if ($display !== null && !is_array ($display)) throw new Exception (_("Display information provided is not an array"), 405); if ($order !== null && !is_array ($order)) throw new Exception (_("Order information provided is not an array"), 405); if ($display !== null) { foreach ($display as $f) { if (!in_array ($f, array_keys ($this->fields))) throw new Exception (sprintf (_("Field %s not allowed"), $f), 506); } } $req = "SELECT "; $req .= implode (",", array_keys ($this->fields)); $req .= " FROM `".$this->table."`"; if ($select !== null) { $req .= " WHERE "; foreach ($select as $n=>$s) { if ($n > 0) $req .= " AND"; if (!isset ($s[2])) $s[2] = "="; $req .= " ".$s[0]." ".$s[2]." :".$s[0]; } } if ($order !== null) { $req .= " ORDER BY "; foreach ($order as $n=>$o) { if ($n > 0) $req .= ","; $req .= $o[0]; if (isset ($o[1]) && $o[1] === "DESC") $req .= " DESC"; else $req .= " ASC"; } } if ($this->debug) echo "DEBUG : $req\n"; $st = $this->db->prepare ($req); if ($select !== NULL) { foreach ($select as $s) { if ($this->debug) echo "DEBUG BIND : ".$s[0]."->". var_export ($s[1], TRUE)."\n"; $st->bindValue (":".$s[0], $s[1]); } } $st->execute (); $res = array (); while ($d = $st->fetch (PDO::FETCH_ASSOC)) $res[] = $d; return $res; } /** Update the key tuple with the provided datas Return the number of rows modified */ function update ($updatekey, $datas) { if ($this->db === null) throw new Exception (_("Database not connected"), 500); $datasOK = array (); // Check for missing parameters foreach ($this->fields as $key=>$params) { // TODO : Check for type inconsistancies before create $datasOK if (array_key_exists ($key, $datas)) $datasOK[$key] = $datas[$key]; } if (count ($datasOK) === 0) throw new Exception (_("Don't receive any field to display"), 501); // Check if the unique constrain is valid before doing the insertion foreach ($this->unique as $columns) { if (is_array ($columns)) { $select = array (); foreach ($columns as $col) { if (!array_key_exists ($col, $datasOK)) continue; $select[] = array ($col, $datasOK[$col]); } $rc = $this->read ($select, array ($this->primary)); if (count ($rc) > 0) throw new Exception (sprintf ( _("The provided value for columns '%s' already exists"), implode (",", $columns)), 405); } else { if (!array_key_exists ($columns, $datasOK)) continue; $rc = $this->read (array (array ($columns, $datasOK[$columns])), array ($this->primary)); if (count ($rc) > 0) throw new Exception (sprintf ( _("The provided value for column '%s' already exists"), $columns), 405); } } // TODO : Check if the foreign keys constrains are valid before doing the $req = "UPDATE `".$this->table."` SET "; $i = 0; foreach ($datasOK as $key=>$val) { if ($i>0) $req .= ","; $req .= "$key=:$key"; $i++; } $req .= " WHERE $this->primary=:primary"; if ($this->debug) echo "DEBUG : $req\n"; $st = $this->db->prepare ($req); if ($this->debug) echo "DEBUG BIND : primary->". var_export ($updatekey, TRUE)."\n"; $st->bindValue (":primary", $updatekey); foreach ($datasOK as $key=>$val) { if ($this->debug) echo "DEBUG BIND : $key->".var_export ($val, TRUE)."\n"; if ($val === null) $st->bindValue (":$key", $val, PDO::PARAM_NULL); elseif ($this->fields[$key][0] === "integer") $st->bindValue (":$key", $val, PDO::PARAM_INT); elseif ($this->fields[$key][0] === "varchar") $st->bindValue (":$key", $val, PDO::PARAM_STR); elseif ($this->fields[$key][0] === "datetime") $st->bindValue (":$key", $val, PDO::PARAM_STR); else throw new Exception ("TO BE DEVELOPPED : ".$this->fields[$key][0], 500); } $st->execute (); return $st->rowCount(); } /** Delete a tuple identified by its primary key Return the number of deleted rows (can be 0 !) */ function delete ($deletekey) { if ($this->db === null) throw new Exception ("Database not connected"); $req = "DELETE FROM `".$this->table."` "; $req .= "WHERE $this->primary = :primary"; $st = $this->db->prepare ($req); if ($this->debug) echo "DEBUG : $req\n"; if ($this->debug) echo "DEBUG BIND : primary->". var_export ($deletekey, TRUE)."\n"; $st->bindValue (":primary", $deletekey); $st->execute (); return $st->rowCount(); } } /** POC : error_reporting (E_ALL); require_once ("domframework/dbLayer.php"); class zone extends dbLayer { // The database must be initialized with // CREATE TABLE `dns_zones` (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, // zone VARCHAR(255) NOT NULL, // viewname VARCHAR(255), // viewclients VARCHAR(255), // comment VARCHAR(1024), // opendate DATETIME NOT NULL, // closedate DATETIME, // UNIQUE (zone,viewname)); protected $table = "dns_zones"; protected $fields = array ( "id"=>array ("integer", "not null", "autoincrement"), "zone"=>array ("varchar", "255", "not null"), "viewname"=>array ("varchar", "255"), "viewclients"=>array ("varchar", "255"), "comment"=>array ("varchar", "1024"), "opendate"=>array ("datetime", "not null"), "closedate"=>array ("datetime"), ); protected $primary = "id"; protected $unique = array ("id", array ("zone", "viewname")); } ini_set ("date.timezone", "Europe/Paris"); $zone = new zone ("sqlite:datas/database.db"); $last = $zone->create (array ("zone"=>"testZone", "opendate"=>date("Y-m-d H:i:s"))); //print_r ($zone->read ()); $zone->update (2040, array ("zone"=>"testZone2")); print_r ($zone->delete ($last)); */