Blame | Last modification | View Log | Download
<?php/*@version V4.80 8 Mar 2006 (c) 2000-2006 John Lim (jlim#natsoft.com.my). All rights reserved.Latest version is available at http://adodb.sourceforge.netReleased under both BSD license and Lesser GPL library license.Whenever there is any discrepancy between the two licenses,the BSD license will take precedence.Active Record implementation. Superset of Zend Framework's.Version 0.02*/global $_ADODB_ACTIVE_DBS;// array of ADODB_Active_DB's, indexed by ADODB_Active_Record->_dbat$_ADODB_ACTIVE_DBS = array();class ADODB_Active_DB {var $db; // ADOConnectionvar $tables; // assoc array of ADODB_Active_Table objects, indexed by tablename}class ADODB_Active_Table {var $name; // table namevar $flds; // assoc array of adofieldobjs, indexed by fieldnamevar $keys; // assoc array of primary keys, indexed by fieldname}// returns index into $_ADODB_ACTIVE_DBSfunction ADODB_SetDatabaseAdapter(&$db){global $_ADODB_ACTIVE_DBS;foreach($_ADODB_ACTIVE_DBS as $k => $d) {if ($d->db == $db) return $k;}$obj = new ADODB_Active_DB();$obj->db =& $db;$obj->tables = array();$_ADODB_ACTIVE_DBS[] = $obj;return sizeof($_ADODB_ACTIVE_DBS)-1;}class ADODB_Active_Record {var $_dbat; // associative index pointing to ADODB_Active_DB eg. $ADODB_Active_DBS[_dbat]var $_table; // tablenamevar $_tableat; // associative index pointing to ADODB_Active_Table, eg $ADODB_Active_DBS[_dbat]->tables[$this->_tableat]var $_where; // where clause set in Load()var $_saved = false; // indicates whether data is already inserted.var $_lasterr = false; // last error message// should be staticfunction SetDatabaseAdapter(&$db){return ADODB_SetDatabaseAdapter($db);}// php4 constructorfunction ADODB_Active_Record($table = false, $pkeyarr=false, $db=false){ADODB_Active_Record::__construct($table,$pkeyarr,$db);}// php5 constructorfunction __construct($table = false, $pkeyarr=false, $db=false){global $ADODB_ASSOC_CASE,$_ADODB_ACTIVE_DBS;if ($db == false && is_object($pkeyarr)) {$db = $pkeyarr;$pkeyarr = false;}if (!$table) $table = $this->_pluralize(get_class($this));if ($db) {$this->_dbat = ADODB_Active_Record::SetDatabaseAdapter($db);} else$this->_dbat = sizeof($_ADODB_ACTIVE_DBS)-1;if ($this->_dbat < 0) $this->Error("No database connection set; use ADOdb_Active_Record::SetDatabaseAdapter(\$db)",'ADODB_Active_Record::__constructor');$this->_table = $table;$this->_tableat = $table; # reserved for setting the assoc value to a non-table name, eg. the sql string in future$this->UpdateActiveTable($pkeyarr);}function _pluralize($table){$ut = strtoupper($table);$len = strlen($table);$lastc = $ut[$len-1];$lastc2 = substr($ut,$len-2);switch ($lastc) {case 'S':return $table.'es';case 'Y':return substr($table,0,$len-1).'ies';case 'X':return $table.'es';case 'H':if ($lastc2 == 'CH' || $lastc2 == 'SH')return $table.'es';default:return $table.'s';}}//////////////////////////////////// update metadatafunction UpdateActiveTable($pkeys=false,$forceUpdate=false){global $ADODB_ASSOC_CASE,$_ADODB_ACTIVE_DBS;$activedb =& $_ADODB_ACTIVE_DBS[$this->_dbat];$table = $this->_table;$tables = $activedb->tables;$tableat = $this->_tableat;if (!$forceUpdate && !empty($tables[$tableat])) {$tobj =& $tables[$tableat];foreach($tobj->flds as $name => $fld)$this->$name = null;return;}$activetab = new ADODB_Active_Table();$activetab->name = $table;$db =& $activedb->db;$cols = $db->MetaColumns($table);if (!$cols) {$this->Error("Invalid table name: $table",'UpdateActiveTable');return false;}$fld = reset($cols);if (!$pkeys) {if (isset($fld->primary_key)) {$pkeys = array();foreach($cols as $name => $fld) {if (!empty($fld->primary_key)) $pkeys[] = $name;}} else$pkeys = $this->GetPrimaryKeys($db, $table);}if (empty($pkeys)) {$this->Error("No primary key found for table $table",'UpdateActiveTable');return false;}$attr = array();$keys = array();switch($ADODB_ASSOC_CASE) {case 0:foreach($cols as $name => $fldobj) {$name = strtolower($name);$this->$name = null;$attr[$name] = $fldobj;}foreach($pkeys as $k => $name) {$keys[strtolower($name)] = strtolower($name);}break;case 1:foreach($cols as $name => $fldobj) {$name = strtoupper($name);$this->$name = null;$attr[$name] = $fldobj;}foreach($pkeys as $k => $name) {$keys[strtoupper($name)] = strtoupper($name);}break;default:foreach($cols as $name => $fldobj) {$name = ($name);$this->$name = null;$attr[$name] = $fldobj;}foreach($pkeys as $k => $name) {$keys[$name] = ($name);}break;}$activetab->keys = $keys;$activetab->flds = $attr;$activedb->tables[$table] = $activetab;}function GetPrimaryKeys(&$db, $table){return $db->MetaPrimaryKeys($table);}// error handler for both PHP4+5.function Error($err,$fn){global $_ADODB_ACTIVE_DBS;$fn = get_class($this).'::'.$fn;$this->_lasterr = $fn.': '.$err;if ($this->_dbat < 0) $db = false;else {$activedb = $_ADODB_ACTIVE_DBS[$this->_dbat];$db =& $activedb->db;}if (function_exists('adodb_throw')) {if (!$db) adodb_throw('ADOdb_Active_Record', $fn, -1, $err, 0, 0, false);else adodb_throw($db->databaseType, $fn, -1, $err, 0, 0, $db);} elseif (!$db || $db->debug) ADOConnection::outp($this->_lasterr);}// return last error messagefunction ErrorMsg(){if (!function_exists('adodb_throw')) {if ($this->_dbat < 0) $db = false;else $db = $this->DB();// last error could be database error tooif ($db && $db->ErrorMsg()) return $db->ErrorMsg();}return $this->_lasterr;}// retrieve ADOConnection from _ADODB_Active_DBsfunction &DB(){global $_ADODB_ACTIVE_DBS;if ($this->_dbat < 0) {$false = false;$this->Error("No database connection set: use ADOdb_Active_Record::SetDatabaseAdaptor(\$db)", "DB");return $false;}$activedb = $_ADODB_ACTIVE_DBS[$this->_dbat];$db =& $activedb->db;return $db;}// retrieve ADODB_Active_Tablefunction &TableInfo(){global $_ADODB_ACTIVE_DBS;$activedb = $_ADODB_ACTIVE_DBS[$this->_dbat];$table =& $activedb->tables[$this->_tableat];return $table;}// set a numeric array (using natural table field ordering) as object propertiesfunction Set(&$row){$db =& $this->DB();if (!$row) {$this->_saved = false;return false;}$this->_saved = true;$table =& $this->TableInfo();if (sizeof($table->flds) != sizeof($row)) {$this->Error("Table structure of $this->_table has changed","Load");return false;}$cnt = 0;foreach($table->flds as $name=>$fld) {$this->$name = $row[$cnt];$cnt += 1;}#$this->_original =& $row;return true;}// get last inserted id for INSERTfunction LastInsertID(&$db,$fieldname){if ($db->hasInsertID)$val = $db->Insert_ID($this->_table,$fieldname);else$val = false;if (is_null($val) || $val === false) {// this might not work reliably in multi-user environmentreturn $db->GetOne("select max(".$fieldname.") from ".$this->_table);}return $val;}// quote data in where clausefunction doquote(&$db, $val,$t){switch($t) {case 'D':case 'T':if (empty($val)) return 'null';case 'C':case 'X':if (is_null($val)) return 'null';if (strncmp($val,"'",1) != 0 && substr($val,strlen($val)-1,1) != "'") {return $db->qstr($val);break;}default:return $val;break;}}// generate where clause for an UPDATE/SELECTfunction GenWhere(&$db, &$table){$keys = $table->keys;$parr = array();foreach($keys as $k) {$f = $table->flds[$k];if ($f) {$parr[] = $k.' = '.$this->doquote($db,$this->$k,$db->MetaType($f->type));}}return implode(' and ', $parr);}//------------------------------------------------------------ Public functions belowfunction Load($where,$bindarr=false){$db =& $this->DB(); if (!$db) return false;$this->_where = $where;$save = $db->SetFetchMode(ADODB_FETCH_NUM);$row = $db->GetRow("select * from ".$this->_table.' WHERE '.$where,$bindarr);$db->SetFetchMode($save);return $this->Set($row);}// false on errorfunction Save(){if ($this->_saved) $ok = $this->Update();else $ok = $this->Insert();return $ok;}// false on errorfunction Insert(){$db =& $this->DB(); if (!$db) return false;$cnt = 0;$table =& $this->TableInfo();foreach($table->flds as $name=>$fld) {$val = $this->$name;/*if (is_null($val)) {if (isset($fld->not_null) && $fld->not_null) {if (isset($fld->default_value) && strlen($fld->default_value)) continue;else $this->Error("Cannot insert null into $name","Insert");}}*/$valarr[] = $val;$names[] = $name;$valstr[] = $db->Param($cnt);$cnt += 1;}$sql = 'INSERT INTO '.$this->_table."(".implode(',',$names).') VALUES ('.implode(',',$valstr).')';$ok = $db->Execute($sql,$valarr);if ($ok) {$this->_saved = true;$autoinc = false;foreach($table->keys as $k) {if (is_null($this->$k)) {$autoinc = true;break;}}if ($autoinc && sizeof($table->keys) == 1) {$k = reset($table->keys);$this->$k = $this->LastInsertID($db,$k);}}#$this->_original =& $valarr;return !empty($ok);}function Delete(){$db =& $this->DB(); if (!$db) return false;$table =& $this->TableInfo();$where = $this->GenWhere($db,$table);$sql = 'DELETE FROM '.$this->_table.' WHERE '.$where;$db->Execute($sql);}// returns 0 on error, 1 on update, 2 on insertfunction Replace(){global $ADODB_ASSOC_CASE;$db =& $this->DB(); if (!$db) return false;$table =& $this->TableInfo();$pkey = $table->keys;foreach($table->flds as $name=>$fld) {$val = $this->$name;/*if (is_null($val)) {if (isset($fld->not_null) && $fld->not_null) {if (isset($fld->default_value) && strlen($fld->default_value)) continue;else {$this->Error("Cannot update null into $name","Replace");return false;}}}*/$t = $db->MetaType($fld->type);$arr[$name] = $this->doquote($db,$val,$t);$valarr[] = $val;}if (!is_array($pkey)) $pkey = array($pkey);if ($ADODB_ASSOC_CASE == 0)foreach($pkey as $k => $v)$pkey[$k] = strtolower($v);elseif ($ADODB_ASSOC_CASE == 0)foreach($pkey as $k => $v)$pkey[$k] = strtoupper($v);$ok = $db->Replace($this->_table,$arr,$pkey);if ($ok) {$this->_saved = true; // 1= update 2=insertif ($ok == 2) {$autoinc = false;foreach($table->keys as $k) {if (is_null($this->$k)) {$autoinc = true;break;}}if ($autoinc && sizeof($table->keys) == 1) {$k = reset($table->keys);$this->$k = $this->LastInsertID($db,$k);}}#$this->_original =& $valarr;}return $ok;}// returns false on errorfunction Update(){$db =& $this->DB(); if (!$db) return false;$table =& $this->TableInfo();$where = $this->GenWhere($db, $table);if (!$where) {$this->error("Where missing for table $table", "Update");return false;}$cnt = 0;foreach($table->flds as $name=>$fld) {if (isset($table->keys[$name])) continue;$val = $this->$name;if (is_null($val)) {if (isset($fld->not_null) && $fld->not_null) {if (isset($fld->default_value) && strlen($fld->default_value)) continue;else {$this->Error("Cannot set field $name to NULL","Update");return false;}}}$valarr[] = $val;$pairs[] = $name.'='.$db->Param($cnt);$cnt += 1;}#$this->_original =& $valarr;$sql = 'UPDATE '.$this->_table." SET ".implode(",",$pairs)." WHERE ".$where;$ok = $db->Execute($sql,$valarr);return !empty($ok);}function GetAttributeNames(){$table =& $this->TableInfo();if (!$table) return false;return array_keys($table->flds);}};?>