Documentation TYPO3 par Ameos |
00001 <?php 00002 /* 00003 00004 @version V4.80 8 Mar 2006 (c) 2000-2006 John Lim (jlim#natsoft.com.my). All rights reserved. 00005 Latest version is available at http://adodb.sourceforge.net 00006 00007 Released under both BSD license and Lesser GPL library license. 00008 Whenever there is any discrepancy between the two licenses, 00009 the BSD license will take precedence. 00010 00011 Active Record implementation. Superset of Zend Framework's. 00012 00013 Version 0.02 00014 */ 00015 00016 global $_ADODB_ACTIVE_DBS; 00017 00018 // array of ADODB_Active_DB's, indexed by ADODB_Active_Record->_dbat 00019 $_ADODB_ACTIVE_DBS = array(); 00020 00021 00022 class ADODB_Active_DB { 00023 var $db; // ADOConnection 00024 var $tables; // assoc array of ADODB_Active_Table objects, indexed by tablename 00025 } 00026 00027 class ADODB_Active_Table { 00028 var $name; // table name 00029 var $flds; // assoc array of adofieldobjs, indexed by fieldname 00030 var $keys; // assoc array of primary keys, indexed by fieldname 00031 } 00032 00033 // returns index into $_ADODB_ACTIVE_DBS 00034 function ADODB_SetDatabaseAdapter(&$db) 00035 { 00036 global $_ADODB_ACTIVE_DBS; 00037 00038 foreach($_ADODB_ACTIVE_DBS as $k => $d) { 00039 if ($d->db == $db) return $k; 00040 } 00041 00042 $obj = new ADODB_Active_DB(); 00043 $obj->db =& $db; 00044 $obj->tables = array(); 00045 00046 $_ADODB_ACTIVE_DBS[] = $obj; 00047 00048 return sizeof($_ADODB_ACTIVE_DBS)-1; 00049 } 00050 00051 class ADODB_Active_Record { 00052 var $_dbat; // associative index pointing to ADODB_Active_DB eg. $ADODB_Active_DBS[_dbat] 00053 var $_table; // tablename 00054 var $_tableat; // associative index pointing to ADODB_Active_Table, eg $ADODB_Active_DBS[_dbat]->tables[$this->_tableat] 00055 var $_where; // where clause set in Load() 00056 var $_saved = false; // indicates whether data is already inserted. 00057 var $_lasterr = false; // last error message 00058 00059 // should be static 00060 function SetDatabaseAdapter(&$db) 00061 { 00062 return ADODB_SetDatabaseAdapter($db); 00063 } 00064 00065 // php4 constructor 00066 function ADODB_Active_Record($table = false, $pkeyarr=false, $db=false) 00067 { 00068 ADODB_Active_Record::__construct($table,$pkeyarr,$db); 00069 } 00070 00071 // php5 constructor 00072 function __construct($table = false, $pkeyarr=false, $db=false) 00073 { 00074 global $ADODB_ASSOC_CASE,$_ADODB_ACTIVE_DBS; 00075 00076 if ($db == false && is_object($pkeyarr)) { 00077 $db = $pkeyarr; 00078 $pkeyarr = false; 00079 } 00080 00081 if (!$table) $table = $this->_pluralize(get_class($this)); 00082 00083 if ($db) { 00084 $this->_dbat = ADODB_Active_Record::SetDatabaseAdapter($db); 00085 } else 00086 $this->_dbat = sizeof($_ADODB_ACTIVE_DBS)-1; 00087 00088 00089 if ($this->_dbat < 0) $this->Error("No database connection set; use ADOdb_Active_Record::SetDatabaseAdapter(\$db)",'ADODB_Active_Record::__constructor'); 00090 00091 $this->_table = $table; 00092 $this->_tableat = $table; # reserved for setting the assoc value to a non-table name, eg. the sql string in future 00093 $this->UpdateActiveTable($pkeyarr); 00094 } 00095 00096 function _pluralize($table) 00097 { 00098 $ut = strtoupper($table); 00099 $len = strlen($table); 00100 $lastc = $ut[$len-1]; 00101 $lastc2 = substr($ut,$len-2); 00102 switch ($lastc) { 00103 case 'S': 00104 return $table.'es'; 00105 case 'Y': 00106 return substr($table,0,$len-1).'ies'; 00107 case 'X': 00108 return $table.'es'; 00109 case 'H': 00110 if ($lastc2 == 'CH' || $lastc2 == 'SH') 00111 return $table.'es'; 00112 default: 00113 return $table.'s'; 00114 } 00115 } 00116 00118 00119 // update metadata 00120 function UpdateActiveTable($pkeys=false,$forceUpdate=false) 00121 { 00122 global $ADODB_ASSOC_CASE,$_ADODB_ACTIVE_DBS; 00123 00124 $activedb =& $_ADODB_ACTIVE_DBS[$this->_dbat]; 00125 00126 $table = $this->_table; 00127 $tables = $activedb->tables; 00128 $tableat = $this->_tableat; 00129 if (!$forceUpdate && !empty($tables[$tableat])) { 00130 $tobj =& $tables[$tableat]; 00131 foreach($tobj->flds as $name => $fld) 00132 $this->$name = null; 00133 return; 00134 } 00135 00136 $activetab = new ADODB_Active_Table(); 00137 $activetab->name = $table; 00138 00139 $db =& $activedb->db; 00140 00141 $cols = $db->MetaColumns($table); 00142 if (!$cols) { 00143 $this->Error("Invalid table name: $table",'UpdateActiveTable'); 00144 return false; 00145 } 00146 $fld = reset($cols); 00147 if (!$pkeys) { 00148 if (isset($fld->primary_key)) { 00149 $pkeys = array(); 00150 foreach($cols as $name => $fld) { 00151 if (!empty($fld->primary_key)) $pkeys[] = $name; 00152 } 00153 } else 00154 $pkeys = $this->GetPrimaryKeys($db, $table); 00155 } 00156 if (empty($pkeys)) { 00157 $this->Error("No primary key found for table $table",'UpdateActiveTable'); 00158 return false; 00159 } 00160 00161 $attr = array(); 00162 $keys = array(); 00163 00164 switch($ADODB_ASSOC_CASE) { 00165 case 0: 00166 foreach($cols as $name => $fldobj) { 00167 $name = strtolower($name); 00168 $this->$name = null; 00169 $attr[$name] = $fldobj; 00170 } 00171 foreach($pkeys as $k => $name) { 00172 $keys[strtolower($name)] = strtolower($name); 00173 } 00174 break; 00175 00176 case 1: 00177 foreach($cols as $name => $fldobj) { 00178 $name = strtoupper($name); 00179 $this->$name = null; 00180 $attr[$name] = $fldobj; 00181 } 00182 00183 foreach($pkeys as $k => $name) { 00184 $keys[strtoupper($name)] = strtoupper($name); 00185 } 00186 break; 00187 default: 00188 foreach($cols as $name => $fldobj) { 00189 $name = ($name); 00190 $this->$name = null; 00191 $attr[$name] = $fldobj; 00192 } 00193 foreach($pkeys as $k => $name) { 00194 $keys[$name] = ($name); 00195 } 00196 break; 00197 } 00198 00199 $activetab->keys = $keys; 00200 $activetab->flds = $attr; 00201 $activedb->tables[$table] = $activetab; 00202 } 00203 00204 function GetPrimaryKeys(&$db, $table) 00205 { 00206 return $db->MetaPrimaryKeys($table); 00207 } 00208 00209 // error handler for both PHP4+5. 00210 function Error($err,$fn) 00211 { 00212 global $_ADODB_ACTIVE_DBS; 00213 00214 $fn = get_class($this).'::'.$fn; 00215 $this->_lasterr = $fn.': '.$err; 00216 00217 if ($this->_dbat < 0) $db = false; 00218 else { 00219 $activedb = $_ADODB_ACTIVE_DBS[$this->_dbat]; 00220 $db =& $activedb->db; 00221 } 00222 00223 if (function_exists('adodb_throw')) { 00224 if (!$db) adodb_throw('ADOdb_Active_Record', $fn, -1, $err, 0, 0, false); 00225 else adodb_throw($db->databaseType, $fn, -1, $err, 0, 0, $db); 00226 } else 00227 if (!$db || $db->debug) ADOConnection::outp($this->_lasterr); 00228 00229 } 00230 00231 // return last error message 00232 function ErrorMsg() 00233 { 00234 if (!function_exists('adodb_throw')) { 00235 if ($this->_dbat < 0) $db = false; 00236 else $db = $this->DB(); 00237 00238 // last error could be database error too 00239 if ($db && $db->ErrorMsg()) return $db->ErrorMsg(); 00240 } 00241 return $this->_lasterr; 00242 } 00243 00244 // retrieve ADOConnection from _ADODB_Active_DBs 00245 function &DB() 00246 { 00247 global $_ADODB_ACTIVE_DBS; 00248 00249 if ($this->_dbat < 0) { 00250 $false = false; 00251 $this->Error("No database connection set: use ADOdb_Active_Record::SetDatabaseAdaptor(\$db)", "DB"); 00252 return $false; 00253 } 00254 $activedb = $_ADODB_ACTIVE_DBS[$this->_dbat]; 00255 $db =& $activedb->db; 00256 return $db; 00257 } 00258 00259 // retrieve ADODB_Active_Table 00260 function &TableInfo() 00261 { 00262 global $_ADODB_ACTIVE_DBS; 00263 00264 $activedb = $_ADODB_ACTIVE_DBS[$this->_dbat]; 00265 $table =& $activedb->tables[$this->_tableat]; 00266 return $table; 00267 } 00268 00269 // set a numeric array (using natural table field ordering) as object properties 00270 function Set(&$row) 00271 { 00272 $db =& $this->DB(); 00273 00274 if (!$row) { 00275 $this->_saved = false; 00276 return false; 00277 } 00278 00279 $this->_saved = true; 00280 00281 $table =& $this->TableInfo(); 00282 if (sizeof($table->flds) != sizeof($row)) { 00283 $this->Error("Table structure of $this->_table has changed","Load"); 00284 return false; 00285 } 00286 00287 $cnt = 0; 00288 foreach($table->flds as $name=>$fld) { 00289 $this->$name = $row[$cnt]; 00290 $cnt += 1; 00291 } 00292 #$this->_original =& $row; 00293 return true; 00294 } 00295 00296 // get last inserted id for INSERT 00297 function LastInsertID(&$db,$fieldname) 00298 { 00299 if ($db->hasInsertID) 00300 $val = $db->Insert_ID($this->_table,$fieldname); 00301 else 00302 $val = false; 00303 00304 if (is_null($val) || $val === false) { 00305 // this might not work reliably in multi-user environment 00306 return $db->GetOne("select max(".$fieldname.") from ".$this->_table); 00307 } 00308 return $val; 00309 } 00310 00311 // quote data in where clause 00312 function doquote(&$db, $val,$t) 00313 { 00314 switch($t) { 00315 case 'D': 00316 case 'T': 00317 if (empty($val)) return 'null'; 00318 00319 case 'C': 00320 case 'X': 00321 if (is_null($val)) return 'null'; 00322 00323 if (strncmp($val,"'",1) != 0 && substr($val,strlen($val)-1,1) != "'") { 00324 return $db->qstr($val); 00325 break; 00326 } 00327 default: 00328 return $val; 00329 break; 00330 } 00331 } 00332 00333 // generate where clause for an UPDATE/SELECT 00334 function GenWhere(&$db, &$table) 00335 { 00336 $keys = $table->keys; 00337 $parr = array(); 00338 00339 foreach($keys as $k) { 00340 $f = $table->flds[$k]; 00341 if ($f) { 00342 $parr[] = $k.' = '.$this->doquote($db,$this->$k,$db->MetaType($f->type)); 00343 } 00344 } 00345 return implode(' and ', $parr); 00346 } 00347 00348 00349 //------------------------------------------------------------ Public functions below 00350 00351 function Load($where,$bindarr=false) 00352 { 00353 $db =& $this->DB(); if (!$db) return false; 00354 $this->_where = $where; 00355 00356 $save = $db->SetFetchMode(ADODB_FETCH_NUM); 00357 $row = $db->GetRow("select * from ".$this->_table.' WHERE '.$where,$bindarr); 00358 $db->SetFetchMode($save); 00359 00360 return $this->Set($row); 00361 } 00362 00363 // false on error 00364 function Save() 00365 { 00366 if ($this->_saved) $ok = $this->Update(); 00367 else $ok = $this->Insert(); 00368 00369 return $ok; 00370 } 00371 00372 // false on error 00373 function Insert() 00374 { 00375 $db =& $this->DB(); if (!$db) return false; 00376 $cnt = 0; 00377 $table =& $this->TableInfo(); 00378 00379 foreach($table->flds as $name=>$fld) { 00380 $val = $this->$name; 00381 /* 00382 if (is_null($val)) { 00383 if (isset($fld->not_null) && $fld->not_null) { 00384 if (isset($fld->default_value) && strlen($fld->default_value)) continue; 00385 else $this->Error("Cannot insert null into $name","Insert"); 00386 } 00387 }*/ 00388 00389 $valarr[] = $val; 00390 $names[] = $name; 00391 $valstr[] = $db->Param($cnt); 00392 $cnt += 1; 00393 } 00394 00395 $sql = 'INSERT INTO '.$this->_table."(".implode(',',$names).') VALUES ('.implode(',',$valstr).')'; 00396 $ok = $db->Execute($sql,$valarr); 00397 00398 if ($ok) { 00399 $this->_saved = true; 00400 $autoinc = false; 00401 foreach($table->keys as $k) { 00402 if (is_null($this->$k)) { 00403 $autoinc = true; 00404 break; 00405 } 00406 } 00407 if ($autoinc && sizeof($table->keys) == 1) { 00408 $k = reset($table->keys); 00409 $this->$k = $this->LastInsertID($db,$k); 00410 } 00411 } 00412 00413 #$this->_original =& $valarr; 00414 return !empty($ok); 00415 } 00416 00417 function Delete() 00418 { 00419 $db =& $this->DB(); if (!$db) return false; 00420 $table =& $this->TableInfo(); 00421 00422 $where = $this->GenWhere($db,$table); 00423 $sql = 'DELETE FROM '.$this->_table.' WHERE '.$where; 00424 $db->Execute($sql); 00425 } 00426 00427 00428 // returns 0 on error, 1 on update, 2 on insert 00429 function Replace() 00430 { 00431 global $ADODB_ASSOC_CASE; 00432 00433 $db =& $this->DB(); if (!$db) return false; 00434 $table =& $this->TableInfo(); 00435 00436 $pkey = $table->keys; 00437 00438 foreach($table->flds as $name=>$fld) { 00439 $val = $this->$name; 00440 /* 00441 if (is_null($val)) { 00442 if (isset($fld->not_null) && $fld->not_null) { 00443 if (isset($fld->default_value) && strlen($fld->default_value)) continue; 00444 else { 00445 $this->Error("Cannot update null into $name","Replace"); 00446 return false; 00447 } 00448 } 00449 }*/ 00450 $t = $db->MetaType($fld->type); 00451 $arr[$name] = $this->doquote($db,$val,$t); 00452 $valarr[] = $val; 00453 } 00454 00455 if (!is_array($pkey)) $pkey = array($pkey); 00456 00457 00458 if ($ADODB_ASSOC_CASE == 0) 00459 foreach($pkey as $k => $v) 00460 $pkey[$k] = strtolower($v); 00461 elseif ($ADODB_ASSOC_CASE == 0) 00462 foreach($pkey as $k => $v) 00463 $pkey[$k] = strtoupper($v); 00464 00465 $ok = $db->Replace($this->_table,$arr,$pkey); 00466 if ($ok) { 00467 $this->_saved = true; // 1= update 2=insert 00468 if ($ok == 2) { 00469 $autoinc = false; 00470 foreach($table->keys as $k) { 00471 if (is_null($this->$k)) { 00472 $autoinc = true; 00473 break; 00474 } 00475 } 00476 if ($autoinc && sizeof($table->keys) == 1) { 00477 $k = reset($table->keys); 00478 $this->$k = $this->LastInsertID($db,$k); 00479 } 00480 } 00481 00482 #$this->_original =& $valarr; 00483 } 00484 return $ok; 00485 } 00486 00487 // returns false on error 00488 function Update() 00489 { 00490 $db =& $this->DB(); if (!$db) return false; 00491 $table =& $this->TableInfo(); 00492 00493 $where = $this->GenWhere($db, $table); 00494 00495 if (!$where) { 00496 $this->error("Where missing for table $table", "Update"); 00497 return false; 00498 } 00499 $cnt = 0; 00500 foreach($table->flds as $name=>$fld) { 00501 if (isset($table->keys[$name])) continue; 00502 00503 $val = $this->$name; 00504 00505 if (is_null($val)) { 00506 if (isset($fld->not_null) && $fld->not_null) { 00507 if (isset($fld->default_value) && strlen($fld->default_value)) continue; 00508 else { 00509 $this->Error("Cannot set field $name to NULL","Update"); 00510 return false; 00511 } 00512 } 00513 } 00514 $valarr[] = $val; 00515 $pairs[] = $name.'='.$db->Param($cnt); 00516 $cnt += 1; 00517 } 00518 00519 #$this->_original =& $valarr; 00520 00521 $sql = 'UPDATE '.$this->_table." SET ".implode(",",$pairs)." WHERE ".$where; 00522 $ok = $db->Execute($sql,$valarr); 00523 00524 return !empty($ok); 00525 } 00526 00527 function GetAttributeNames() 00528 { 00529 $table =& $this->TableInfo(); 00530 if (!$table) return false; 00531 return array_keys($table->flds); 00532 } 00533 00534 }; 00535 00536 ?>