| [ Index ] |
PHP Cross Reference of MantisBT |
[Summary view] [Print] [Text view]
1 <?php 2 /* 3 4 @version V5.11 5 May 2010 (c) 2000-2010 John Lim (jlim#natsoft.com). All rights reserved. 5 Latest version is available at http://adodb.sourceforge.net 6 7 Released under both BSD license and Lesser GPL library license. 8 Whenever there is any discrepancy between the two licenses, 9 the BSD license will take precedence. 10 11 Active Record implementation. Superset of Zend Framework's. 12 13 Version 0.92 14 15 See http://www-128.ibm.com/developerworks/java/library/j-cb03076/?ca=dgr-lnxw01ActiveRecord 16 for info on Ruby on Rails Active Record implementation 17 */ 18 19 20 global $_ADODB_ACTIVE_DBS; 21 global $ADODB_ACTIVE_CACHESECS; // set to true to enable caching of metadata such as field info 22 global $ACTIVE_RECORD_SAFETY; // set to false to disable safety checks 23 global $ADODB_ACTIVE_DEFVALS; // use default values of table definition when creating new active record. 24 25 // array of ADODB_Active_DB's, indexed by ADODB_Active_Record->_dbat 26 $_ADODB_ACTIVE_DBS = array(); 27 $ACTIVE_RECORD_SAFETY = true; 28 $ADODB_ACTIVE_DEFVALS = false; 29 $ADODB_ACTIVE_CACHESECS = 0; 30 31 class ADODB_Active_DB { 32 var $db; // ADOConnection 33 var $tables; // assoc array of ADODB_Active_Table objects, indexed by tablename 34 } 35 36 class ADODB_Active_Table { 37 var $name; // table name 38 var $flds; // assoc array of adofieldobjs, indexed by fieldname 39 var $keys; // assoc array of primary keys, indexed by fieldname 40 var $_created; // only used when stored as a cached file 41 var $_belongsTo = array(); 42 var $_hasMany = array(); 43 } 44 45 // $db = database connection 46 // $index = name of index - can be associative, for an example see 47 // http://phplens.com/lens/lensforum/msgs.php?id=17790 48 // returns index into $_ADODB_ACTIVE_DBS 49 function ADODB_SetDatabaseAdapter(&$db, $index=false) 50 { 51 global $_ADODB_ACTIVE_DBS; 52 53 foreach($_ADODB_ACTIVE_DBS as $k => $d) { 54 if (PHP_VERSION >= 5) { 55 if ($d->db === $db) return $k; 56 } else { 57 if ($d->db->_connectionID === $db->_connectionID && $db->database == $d->db->database) 58 return $k; 59 } 60 } 61 62 $obj = new ADODB_Active_DB(); 63 $obj->db = $db; 64 $obj->tables = array(); 65 66 if ($index == false) $index = sizeof($_ADODB_ACTIVE_DBS); 67 68 69 $_ADODB_ACTIVE_DBS[$index] = $obj; 70 71 return sizeof($_ADODB_ACTIVE_DBS)-1; 72 } 73 74 75 class ADODB_Active_Record { 76 static $_changeNames = true; // dynamically pluralize table names 77 static $_quoteNames = false; 78 79 static $_foreignSuffix = '_id'; // 80 var $_dbat; // associative index pointing to ADODB_Active_DB eg. $ADODB_Active_DBS[_dbat] 81 var $_table; // tablename, if set in class definition then use it as table name 82 var $_tableat; // associative index pointing to ADODB_Active_Table, eg $ADODB_Active_DBS[_dbat]->tables[$this->_tableat] 83 var $_where; // where clause set in Load() 84 var $_saved = false; // indicates whether data is already inserted. 85 var $_lasterr = false; // last error message 86 var $_original = false; // the original values loaded or inserted, refreshed on update 87 88 var $foreignName; // CFR: class name when in a relationship 89 90 static function UseDefaultValues($bool=null) 91 { 92 global $ADODB_ACTIVE_DEFVALS; 93 if (isset($bool)) $ADODB_ACTIVE_DEFVALS = $bool; 94 return $ADODB_ACTIVE_DEFVALS; 95 } 96 97 // should be static 98 static function SetDatabaseAdapter(&$db, $index=false) 99 { 100 return ADODB_SetDatabaseAdapter($db, $index); 101 } 102 103 104 public function __set($name, $value) 105 { 106 $name = str_replace(' ', '_', $name); 107 $this->$name = $value; 108 } 109 110 // php5 constructor 111 function __construct($table = false, $pkeyarr=false, $db=false) 112 { 113 global $ADODB_ASSOC_CASE,$_ADODB_ACTIVE_DBS; 114 115 if ($db == false && is_object($pkeyarr)) { 116 $db = $pkeyarr; 117 $pkeyarr = false; 118 } 119 120 if (!$table) { 121 if (!empty($this->_table)) $table = $this->_table; 122 else $table = $this->_pluralize(get_class($this)); 123 } 124 $this->foreignName = strtolower(get_class($this)); // CFR: default foreign name 125 if ($db) { 126 $this->_dbat = ADODB_Active_Record::SetDatabaseAdapter($db); 127 } else if (!isset($this->_dbat)) { 128 if (sizeof($_ADODB_ACTIVE_DBS) == 0) $this->Error("No database connection set; use ADOdb_Active_Record::SetDatabaseAdapter(\$db)",'ADODB_Active_Record::__constructor'); 129 end($_ADODB_ACTIVE_DBS); 130 $this->_dbat = key($_ADODB_ACTIVE_DBS); 131 } 132 133 $this->_table = $table; 134 $this->_tableat = $table; # reserved for setting the assoc value to a non-table name, eg. the sql string in future 135 136 $this->UpdateActiveTable($pkeyarr); 137 } 138 139 function __wakeup() 140 { 141 $class = get_class($this); 142 new $class; 143 } 144 145 function _pluralize($table) 146 { 147 if (!ADODB_Active_Record::$_changeNames) return $table; 148 149 $ut = strtoupper($table); 150 $len = strlen($table); 151 $lastc = $ut[$len-1]; 152 $lastc2 = substr($ut,$len-2); 153 switch ($lastc) { 154 case 'S': 155 return $table.'es'; 156 case 'Y': 157 return substr($table,0,$len-1).'ies'; 158 case 'X': 159 return $table.'es'; 160 case 'H': 161 if ($lastc2 == 'CH' || $lastc2 == 'SH') 162 return $table.'es'; 163 default: 164 return $table.'s'; 165 } 166 } 167 168 // CFR Lamest singular inflector ever - @todo Make it real! 169 // Note: There is an assumption here...and it is that the argument's length >= 4 170 function _singularize($tables) 171 { 172 173 if (!ADODB_Active_Record::$_changeNames) return $table; 174 175 $ut = strtoupper($tables); 176 $len = strlen($tables); 177 if($ut[$len-1] != 'S') 178 return $tables; // I know...forget oxen 179 if($ut[$len-2] != 'E') 180 return substr($tables, 0, $len-1); 181 switch($ut[$len-3]) 182 { 183 case 'S': 184 case 'X': 185 return substr($tables, 0, $len-2); 186 case 'I': 187 return substr($tables, 0, $len-3) . 'y'; 188 case 'H'; 189 if($ut[$len-4] == 'C' || $ut[$len-4] == 'S') 190 return substr($tables, 0, $len-2); 191 default: 192 return substr($tables, 0, $len-1); // ? 193 } 194 } 195 196 function hasMany($foreignRef, $foreignKey = false, $foreignClass = 'ADODB_Active_Record') 197 { 198 $ar = new $foreignClass($foreignRef); 199 $ar->foreignName = $foreignRef; 200 $ar->UpdateActiveTable(); 201 $ar->foreignKey = ($foreignKey) ? $foreignKey : $foreignRef.ADODB_Active_Record::$_foreignSuffix; 202 $table =& $this->TableInfo(); 203 $table->_hasMany[$foreignRef] = $ar; 204 # $this->$foreignRef = $this->_hasMany[$foreignRef]; // WATCHME Removed assignment by ref. to please __get() 205 } 206 207 // use when you don't want ADOdb to auto-pluralize tablename 208 static function TableHasMany($table, $foreignRef, $foreignKey = false, $foreignClass = 'ADODB_Active_Record') 209 { 210 $ar = new ADODB_Active_Record($table); 211 $ar->hasMany($foreignRef, $foreignKey, $foreignClass); 212 } 213 214 // use when you don't want ADOdb to auto-pluralize tablename 215 static function TableKeyHasMany($table, $tablePKey, $foreignRef, $foreignKey = false, $foreignClass = 'ADODB_Active_Record') 216 { 217 if (!is_array($tablePKey)) $tablePKey = array($tablePKey); 218 $ar = new ADODB_Active_Record($table,$tablePKey); 219 $ar->hasMany($foreignRef, $foreignKey, $foreignClass); 220 } 221 222 223 // use when you want ADOdb to auto-pluralize tablename for you. Note that the class must already be defined. 224 // e.g. class Person will generate relationship for table Persons 225 static function ClassHasMany($parentclass, $foreignRef, $foreignKey = false, $foreignClass = 'ADODB_Active_Record') 226 { 227 $ar = new $parentclass(); 228 $ar->hasMany($foreignRef, $foreignKey, $foreignClass); 229 } 230 231 232 function belongsTo($foreignRef,$foreignKey=false, $parentKey='', $parentClass = 'ADODB_Active_Record') 233 { 234 global $inflector; 235 236 $ar = new $parentClass($this->_pluralize($foreignRef)); 237 $ar->foreignName = $foreignRef; 238 $ar->parentKey = $parentKey; 239 $ar->UpdateActiveTable(); 240 $ar->foreignKey = ($foreignKey) ? $foreignKey : $foreignRef.ADODB_Active_Record::$_foreignSuffix; 241 242 $table =& $this->TableInfo(); 243 $table->_belongsTo[$foreignRef] = $ar; 244 # $this->$foreignRef = $this->_belongsTo[$foreignRef]; 245 } 246 247 static function ClassBelongsTo($class, $foreignRef, $foreignKey=false, $parentKey='', $parentClass = 'ADODB_Active_Record') 248 { 249 $ar = new $class(); 250 $ar->belongsTo($foreignRef, $foreignKey, $parentKey, $parentClass); 251 } 252 253 static function TableBelongsTo($table, $foreignRef, $foreignKey=false, $parentKey='', $parentClass = 'ADODB_Active_Record') 254 { 255 $ar = new ADOdb_Active_Record($table); 256 $ar->belongsTo($foreignRef, $foreignKey, $parentKey, $parentClass); 257 } 258 259 static function TableKeyBelongsTo($table, $tablePKey, $foreignRef, $foreignKey=false, $parentKey='', $parentClass = 'ADODB_Active_Record') 260 { 261 if (!is_array($tablePKey)) $tablePKey = array($tablePKey); 262 $ar = new ADOdb_Active_Record($table, $tablePKey); 263 $ar->belongsTo($foreignRef, $foreignKey, $parentKey, $parentClass); 264 } 265 266 267 /** 268 * __get Access properties - used for lazy loading 269 * 270 * @param mixed $name 271 * @access protected 272 * @return mixed 273 */ 274 function __get($name) 275 { 276 return $this->LoadRelations($name, '', -1, -1); 277 } 278 279 /** 280 * @param string $name 281 * @param string $whereOrderBy : eg. ' AND field1 = value ORDER BY field2' 282 * @param offset 283 * @param limit 284 * @return mixed 285 */ 286 function LoadRelations($name, $whereOrderBy='', $offset=-1,$limit=-1) 287 { 288 $extras = array(); 289 $table = $this->TableInfo(); 290 if ($limit >= 0) $extras['limit'] = $limit; 291 if ($offset >= 0) $extras['offset'] = $offset; 292 293 if (strlen($whereOrderBy)) 294 if (!preg_match('/^[ \n\r]*AND/i',$whereOrderBy)) 295 if (!preg_match('/^[ \n\r]*ORDER[ \n\r]/i',$whereOrderBy)) 296 $whereOrderBy = 'AND '.$whereOrderBy; 297 298 if(!empty($table->_belongsTo[$name])) 299 { 300 $obj = $table->_belongsTo[$name]; 301 $columnName = $obj->foreignKey; 302 if(empty($this->$columnName)) 303 $this->$name = null; 304 else 305 { 306 if ($obj->parentKey) $key = $obj->parentKey; 307 else $key = reset($table->keys); 308 309 $arrayOfOne = $obj->Find($key.'='.$this->$columnName.' '.$whereOrderBy,false,false,$extras); 310 if ($arrayOfOne) { 311 $this->$name = $arrayOfOne[0]; 312 return $arrayOfOne[0]; 313 } 314 } 315 } 316 if(!empty($table->_hasMany[$name])) 317 { 318 $obj = $table->_hasMany[$name]; 319 $key = reset($table->keys); 320 $id = @$this->$key; 321 if (!is_numeric($id)) { 322 $db = $this->DB(); 323 $id = $db->qstr($id); 324 } 325 $objs = $obj->Find($obj->foreignKey.'='.$id. ' '.$whereOrderBy,false,false,$extras); 326 if (!$objs) $objs = array(); 327 $this->$name = $objs; 328 return $objs; 329 } 330 331 return array(); 332 } 333 ////////////////////////////////// 334 335 // update metadata 336 function UpdateActiveTable($pkeys=false,$forceUpdate=false) 337 { 338 global $ADODB_ASSOC_CASE,$_ADODB_ACTIVE_DBS , $ADODB_CACHE_DIR, $ADODB_ACTIVE_CACHESECS; 339 global $ADODB_ACTIVE_DEFVALS,$ADODB_FETCH_MODE; 340 341 $activedb = $_ADODB_ACTIVE_DBS[$this->_dbat]; 342 343 $table = $this->_table; 344 $tables = $activedb->tables; 345 $tableat = $this->_tableat; 346 if (!$forceUpdate && !empty($tables[$tableat])) { 347 348 $acttab = $tables[$tableat]; 349 foreach($acttab->flds as $name => $fld) { 350 if ($ADODB_ACTIVE_DEFVALS && isset($fld->default_value)) 351 $this->$name = $fld->default_value; 352 else 353 $this->$name = null; 354 } 355 return; 356 } 357 $db = $activedb->db; 358 $fname = $ADODB_CACHE_DIR . '/adodb_' . $db->databaseType . '_active_'. $table . '.cache'; 359 if (!$forceUpdate && $ADODB_ACTIVE_CACHESECS && $ADODB_CACHE_DIR && file_exists($fname)) { 360 $fp = fopen($fname,'r'); 361 @flock($fp, LOCK_SH); 362 $acttab = unserialize(fread($fp,100000)); 363 fclose($fp); 364 if ($acttab->_created + $ADODB_ACTIVE_CACHESECS - (abs(rand()) % 16) > time()) { 365 // abs(rand()) randomizes deletion, reducing contention to delete/refresh file 366 // ideally, you should cache at least 32 secs 367 368 foreach($acttab->flds as $name => $fld) { 369 if ($ADODB_ACTIVE_DEFVALS && isset($fld->default_value)) 370 $this->$name = $fld->default_value; 371 else 372 $this->$name = null; 373 } 374 375 $activedb->tables[$table] = $acttab; 376 377 //if ($db->debug) ADOConnection::outp("Reading cached active record file: $fname"); 378 return; 379 } else if ($db->debug) { 380 ADOConnection::outp("Refreshing cached active record file: $fname"); 381 } 382 } 383 $activetab = new ADODB_Active_Table(); 384 $activetab->name = $table; 385 386 $save = $ADODB_FETCH_MODE; 387 $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC; 388 if ($db->fetchMode !== false) $savem = $db->SetFetchMode(false); 389 390 $cols = $db->MetaColumns($table); 391 392 if (isset($savem)) $db->SetFetchMode($savem); 393 $ADODB_FETCH_MODE = $save; 394 395 if (!$cols) { 396 $this->Error("Invalid table name: $table",'UpdateActiveTable'); 397 return false; 398 } 399 $fld = reset($cols); 400 if (!$pkeys) { 401 if (isset($fld->primary_key)) { 402 $pkeys = array(); 403 foreach($cols as $name => $fld) { 404 if (!empty($fld->primary_key)) $pkeys[] = $name; 405 } 406 } else 407 $pkeys = $this->GetPrimaryKeys($db, $table); 408 } 409 if (empty($pkeys)) { 410 $this->Error("No primary key found for table $table",'UpdateActiveTable'); 411 return false; 412 } 413 414 $attr = array(); 415 $keys = array(); 416 417 switch($ADODB_ASSOC_CASE) { 418 case 0: 419 foreach($cols as $name => $fldobj) { 420 $name = strtolower($name); 421 if ($ADODB_ACTIVE_DEFVALS && isset($fldobj->default_value)) 422 $this->$name = $fldobj->default_value; 423 else 424 $this->$name = null; 425 $attr[$name] = $fldobj; 426 } 427 foreach($pkeys as $k => $name) { 428 $keys[strtolower($name)] = strtolower($name); 429 } 430 break; 431 432 case 1: 433 foreach($cols as $name => $fldobj) { 434 $name = strtoupper($name); 435 436 if ($ADODB_ACTIVE_DEFVALS && isset($fldobj->default_value)) 437 $this->$name = $fldobj->default_value; 438 else 439 $this->$name = null; 440 $attr[$name] = $fldobj; 441 } 442 443 foreach($pkeys as $k => $name) { 444 $keys[strtoupper($name)] = strtoupper($name); 445 } 446 break; 447 default: 448 foreach($cols as $name => $fldobj) { 449 $name = ($fldobj->name); 450 451 if ($ADODB_ACTIVE_DEFVALS && isset($fldobj->default_value)) 452 $this->$name = $fldobj->default_value; 453 else 454 $this->$name = null; 455 $attr[$name] = $fldobj; 456 } 457 foreach($pkeys as $k => $name) { 458 $keys[$name] = $cols[$name]->name; 459 } 460 break; 461 } 462 463 $activetab->keys = $keys; 464 $activetab->flds = $attr; 465 466 if ($ADODB_ACTIVE_CACHESECS && $ADODB_CACHE_DIR) { 467 $activetab->_created = time(); 468 $s = serialize($activetab); 469 if (!function_exists('adodb_write_file')) include (ADODB_DIR.'/adodb-csvlib.inc.php'); 470 adodb_write_file($fname,$s); 471 } 472 if (isset($activedb->tables[$table])) { 473 $oldtab = $activedb->tables[$table]; 474 475 if ($oldtab) $activetab->_belongsTo = $oldtab->_belongsTo; 476 if ($oldtab) $activetab->_hasMany = $oldtab->_hasMany; 477 } 478 $activedb->tables[$table] = $activetab; 479 } 480 481 function GetPrimaryKeys(&$db, $table) 482 { 483 return $db->MetaPrimaryKeys($table); 484 } 485 486 // error handler for both PHP4+5. 487 function Error($err,$fn) 488 { 489 global $_ADODB_ACTIVE_DBS; 490 491 $fn = get_class($this).'::'.$fn; 492 $this->_lasterr = $fn.': '.$err; 493 494 if ($this->_dbat < 0) $db = false; 495 else { 496 $activedb = $_ADODB_ACTIVE_DBS[$this->_dbat]; 497 $db = $activedb->db; 498 } 499 500 if (function_exists('adodb_throw')) { 501 if (!$db) adodb_throw('ADOdb_Active_Record', $fn, -1, $err, 0, 0, false); 502 else adodb_throw($db->databaseType, $fn, -1, $err, 0, 0, $db); 503 } else 504 if (!$db || $db->debug) ADOConnection::outp($this->_lasterr); 505 506 } 507 508 // return last error message 509 function ErrorMsg() 510 { 511 if (!function_exists('adodb_throw')) { 512 if ($this->_dbat < 0) $db = false; 513 else $db = $this->DB(); 514 515 // last error could be database error too 516 if ($db && $db->ErrorMsg()) return $db->ErrorMsg(); 517 } 518 return $this->_lasterr; 519 } 520 521 function ErrorNo() 522 { 523 if ($this->_dbat < 0) return -9999; // no database connection... 524 $db = $this->DB(); 525 526 return (int) $db->ErrorNo(); 527 } 528 529 530 // retrieve ADOConnection from _ADODB_Active_DBs 531 function DB() 532 { 533 global $_ADODB_ACTIVE_DBS; 534 535 if ($this->_dbat < 0) { 536 $false = false; 537 $this->Error("No database connection set: use ADOdb_Active_Record::SetDatabaseAdaptor(\$db)", "DB"); 538 return $false; 539 } 540 $activedb = $_ADODB_ACTIVE_DBS[$this->_dbat]; 541 $db = $activedb->db; 542 return $db; 543 } 544 545 // retrieve ADODB_Active_Table 546 function &TableInfo() 547 { 548 global $_ADODB_ACTIVE_DBS; 549 $activedb = $_ADODB_ACTIVE_DBS[$this->_dbat]; 550 $table = $activedb->tables[$this->_tableat]; 551 return $table; 552 } 553 554 555 // I have an ON INSERT trigger on a table that sets other columns in the table. 556 // So, I find that for myTable, I want to reload an active record after saving it. -- Malcolm Cook 557 function Reload() 558 { 559 $db =& $this->DB(); if (!$db) return false; 560 $table =& $this->TableInfo(); 561 $where = $this->GenWhere($db, $table); 562 return($this->Load($where)); 563 } 564 565 566 // set a numeric array (using natural table field ordering) as object properties 567 function Set(&$row) 568 { 569 global $ACTIVE_RECORD_SAFETY; 570 571 $db = $this->DB(); 572 573 if (!$row) { 574 $this->_saved = false; 575 return false; 576 } 577 578 $this->_saved = true; 579 580 $table = $this->TableInfo(); 581 if ($ACTIVE_RECORD_SAFETY && sizeof($table->flds) != sizeof($row)) { 582 # <AP> 583 $bad_size = TRUE; 584 if (sizeof($row) == 2 * sizeof($table->flds)) { 585 // Only keep string keys 586 $keys = array_filter(array_keys($row), 'is_string'); 587 if (sizeof($keys) == sizeof($table->flds)) 588 $bad_size = FALSE; 589 } 590 if ($bad_size) { 591 $this->Error("Table structure of $this->_table has changed","Load"); 592 return false; 593 } 594 # </AP> 595 } 596 else 597 $keys = array_keys($row); 598 599 # <AP> 600 reset($keys); 601 $this->_original = array(); 602 foreach($table->flds as $name=>$fld) { 603 $value = $row[current($keys)]; 604 $this->$name = $value; 605 $this->_original[] = $value; 606 next($keys); 607 } 608 609 # </AP> 610 return true; 611 } 612 613 // get last inserted id for INSERT 614 function LastInsertID(&$db,$fieldname) 615 { 616 if ($db->hasInsertID) 617 $val = $db->Insert_ID($this->_table,$fieldname); 618 else 619 $val = false; 620 621 if (is_null($val) || $val === false) { 622 // this might not work reliably in multi-user environment 623 return $db->GetOne("select max(".$fieldname.") from ".$this->_table); 624 } 625 return $val; 626 } 627 628 // quote data in where clause 629 function doquote(&$db, $val,$t) 630 { 631 switch($t) { 632 case 'L': 633 if (strpos($db->databaseType,'postgres') !== false) return $db->qstr($val); 634 case 'D': 635 case 'T': 636 if (empty($val)) return 'null'; 637 638 case 'B': 639 case 'N': 640 case 'C': 641 case 'X': 642 if (is_null($val)) return 'null'; 643 644 if (strlen($val)>1 && 645 (strncmp($val,"'",1) != 0 || substr($val,strlen($val)-1,1) != "'")) { 646 return $db->qstr($val); 647 break; 648 } 649 default: 650 return $val; 651 break; 652 } 653 } 654 655 // generate where clause for an UPDATE/SELECT 656 function GenWhere(&$db, &$table) 657 { 658 $keys = $table->keys; 659 $parr = array(); 660 661 foreach($keys as $k) { 662 $f = $table->flds[$k]; 663 if ($f) { 664 $parr[] = $k.' = '.$this->doquote($db,$this->$k,$db->MetaType($f->type)); 665 } 666 } 667 return implode(' and ', $parr); 668 } 669 670 671 function _QName($n,$db=false) 672 { 673 if (!ADODB_Active_Record::$_quoteNames) return $n; 674 if (!$db) $db = $this->DB(); if (!$db) return false; 675 return $db->nameQuote.$n.$db->nameQuote; 676 } 677 678 //------------------------------------------------------------ Public functions below 679 680 function Load($where=null,$bindarr=false) 681 { 682 global $ADODB_FETCH_MODE; 683 684 $db = $this->DB(); if (!$db) return false; 685 $this->_where = $where; 686 687 $save = $ADODB_FETCH_MODE; 688 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 689 if ($db->fetchMode !== false) $savem = $db->SetFetchMode(false); 690 691 $qry = "select * from ".$this->_table; 692 693 if($where) { 694 $qry .= ' WHERE '.$where; 695 } 696 $row = $db->GetRow($qry,$bindarr); 697 698 if (isset($savem)) $db->SetFetchMode($savem); 699 $ADODB_FETCH_MODE = $save; 700 701 return $this->Set($row); 702 } 703 704 # useful for multiple record inserts 705 # see http://phplens.com/lens/lensforum/msgs.php?id=17795 706 function Reset() 707 { 708 $this->_where=null; 709 $this->_saved = false; 710 $this->_lasterr = false; 711 $this->_original = false; 712 $vars=get_object_vars($this); 713 foreach($vars as $k=>$v){ 714 if(substr($k,0,1)!=='_'){ 715 $this->{$k}=null; 716 } 717 } 718 $this->foreignName=strtolower(get_class($this)); 719 return true; 720 } 721 722 // false on error 723 function Save() 724 { 725 if ($this->_saved) $ok = $this->Update(); 726 else $ok = $this->Insert(); 727 728 return $ok; 729 } 730 731 732 // false on error 733 function Insert() 734 { 735 $db = $this->DB(); if (!$db) return false; 736 $cnt = 0; 737 $table = $this->TableInfo(); 738 739 $valarr = array(); 740 $names = array(); 741 $valstr = array(); 742 743 foreach($table->flds as $name=>$fld) { 744 $val = $this->$name; 745 if(!is_array($val) || !is_null($val) || !array_key_exists($name, $table->keys)) { 746 $valarr[] = $val; 747 $names[] = $this->_QName($name,$db); 748 $valstr[] = $db->Param($cnt); 749 $cnt += 1; 750 } 751 } 752 753 if (empty($names)){ 754 foreach($table->flds as $name=>$fld) { 755 $valarr[] = null; 756 $names[] = $name; 757 $valstr[] = $db->Param($cnt); 758 $cnt += 1; 759 } 760 } 761 $sql = 'INSERT INTO '.$this->_table."(".implode(',',$names).') VALUES ('.implode(',',$valstr).')'; 762 $ok = $db->Execute($sql,$valarr); 763 764 if ($ok) { 765 $this->_saved = true; 766 $autoinc = false; 767 foreach($table->keys as $k) { 768 if (is_null($this->$k)) { 769 $autoinc = true; 770 break; 771 } 772 } 773 if ($autoinc && sizeof($table->keys) == 1) { 774 $k = reset($table->keys); 775 $this->$k = $this->LastInsertID($db,$k); 776 } 777 } 778 779 $this->_original = $valarr; 780 return !empty($ok); 781 } 782 783 function Delete() 784 { 785 $db = $this->DB(); if (!$db) return false; 786 $table = $this->TableInfo(); 787 788 $where = $this->GenWhere($db,$table); 789 $sql = 'DELETE FROM '.$this->_table.' WHERE '.$where; 790 $ok = $db->Execute($sql); 791 792 return $ok ? true : false; 793 } 794 795 // returns an array of active record objects 796 function Find($whereOrderBy,$bindarr=false,$pkeysArr=false,$extra=array()) 797 { 798 $db = $this->DB(); if (!$db || empty($this->_table)) return false; 799 $arr = $db->GetActiveRecordsClass(get_class($this),$this->_table, $whereOrderBy,$bindarr,$pkeysArr,$extra); 800 return $arr; 801 } 802 803 // returns 0 on error, 1 on update, 2 on insert 804 function Replace() 805 { 806 global $ADODB_ASSOC_CASE; 807 808 $db = $this->DB(); if (!$db) return false; 809 $table = $this->TableInfo(); 810 811 $pkey = $table->keys; 812 813 foreach($table->flds as $name=>$fld) { 814 $val = $this->$name; 815 /* 816 if (is_null($val)) { 817 if (isset($fld->not_null) && $fld->not_null) { 818 if (isset($fld->default_value) && strlen($fld->default_value)) continue; 819 else { 820 $this->Error("Cannot update null into $name","Replace"); 821 return false; 822 } 823 } 824 }*/ 825 if (is_null($val) && !empty($fld->auto_increment)) { 826 continue; 827 } 828 829 if (is_array($val)) continue; 830 831 $t = $db->MetaType($fld->type); 832 $arr[$name] = $this->doquote($db,$val,$t); 833 $valarr[] = $val; 834 } 835 836 if (!is_array($pkey)) $pkey = array($pkey); 837 838 839 if ($ADODB_ASSOC_CASE == 0) 840 foreach($pkey as $k => $v) 841 $pkey[$k] = strtolower($v); 842 elseif ($ADODB_ASSOC_CASE == 1) 843 foreach($pkey as $k => $v) 844 $pkey[$k] = strtoupper($v); 845 846 $ok = $db->Replace($this->_table,$arr,$pkey); 847 if ($ok) { 848 $this->_saved = true; // 1= update 2=insert 849 if ($ok == 2) { 850 $autoinc = false; 851 foreach($table->keys as $k) { 852 if (is_null($this->$k)) { 853 $autoinc = true; 854 break; 855 } 856 } 857 if ($autoinc && sizeof($table->keys) == 1) { 858 $k = reset($table->keys); 859 $this->$k = $this->LastInsertID($db,$k); 860 } 861 } 862 863 $this->_original = $valarr; 864 } 865 return $ok; 866 } 867 868 // returns 0 on error, 1 on update, -1 if no change in data (no update) 869 function Update() 870 { 871 $db = $this->DB(); if (!$db) return false; 872 $table = $this->TableInfo(); 873 874 $where = $this->GenWhere($db, $table); 875 876 if (!$where) { 877 $this->error("Where missing for table $table", "Update"); 878 return false; 879 } 880 $valarr = array(); 881 $neworig = array(); 882 $pairs = array(); 883 $i = -1; 884 $cnt = 0; 885 foreach($table->flds as $name=>$fld) { 886 $i += 1; 887 $val = $this->$name; 888 $neworig[] = $val; 889 890 if (isset($table->keys[$name]) || is_array($val)) 891 continue; 892 893 if (is_null($val)) { 894 if (isset($fld->not_null) && $fld->not_null) { 895 if (isset($fld->default_value) && strlen($fld->default_value)) continue; 896 else { 897 $this->Error("Cannot set field $name to NULL","Update"); 898 return false; 899 } 900 } 901 } 902 903 if (isset($this->_original[$i]) && strcmp($val,$this->_original[$i]) == 0) { 904 continue; 905 } 906 $valarr[] = $val; 907 $pairs[] = $this->_QName($name,$db).'='.$db->Param($cnt); 908 $cnt += 1; 909 } 910 911 912 if (!$cnt) return -1; 913 $sql = 'UPDATE '.$this->_table." SET ".implode(",",$pairs)." WHERE ".$where; 914 $ok = $db->Execute($sql,$valarr); 915 if ($ok) { 916 $this->_original = $neworig; 917 return 1; 918 } 919 return 0; 920 } 921 922 function GetAttributeNames() 923 { 924 $table = $this->TableInfo(); 925 if (!$table) return false; 926 return array_keys($table->flds); 927 } 928 929 }; 930 931 function adodb_GetActiveRecordsClass(&$db, $class, $table,$whereOrderBy,$bindarr, $primkeyArr, 932 $extra) 933 { 934 global $_ADODB_ACTIVE_DBS; 935 936 937 $save = $db->SetFetchMode(ADODB_FETCH_NUM); 938 $qry = "select * from ".$table; 939 940 if (!empty($whereOrderBy)) 941 $qry .= ' WHERE '.$whereOrderBy; 942 if(isset($extra['limit'])) 943 { 944 $rows = false; 945 if(isset($extra['offset'])) { 946 $rs = $db->SelectLimit($qry, $extra['limit'], $extra['offset'],$bindarr); 947 } else { 948 $rs = $db->SelectLimit($qry, $extra['limit'],-1,$bindarr); 949 } 950 if ($rs) { 951 while (!$rs->EOF) { 952 $rows[] = $rs->fields; 953 $rs->MoveNext(); 954 } 955 } 956 } else 957 $rows = $db->GetAll($qry,$bindarr); 958 959 $db->SetFetchMode($save); 960 961 $false = false; 962 963 if ($rows === false) { 964 return $false; 965 } 966 967 968 if (!class_exists($class)) { 969 $db->outp_throw("Unknown class $class in GetActiveRecordsClass()",'GetActiveRecordsClass'); 970 return $false; 971 } 972 $arr = array(); 973 // arrRef will be the structure that knows about our objects. 974 // It is an associative array. 975 // We will, however, return arr, preserving regular 0.. order so that 976 // obj[0] can be used by app developpers. 977 $arrRef = array(); 978 $bTos = array(); // Will store belongTo's indices if any 979 foreach($rows as $row) { 980 981 $obj = new $class($table,$primkeyArr,$db); 982 if ($obj->ErrorNo()){ 983 $db->_errorMsg = $obj->ErrorMsg(); 984 return $false; 985 } 986 $obj->Set($row); 987 $arr[] = $obj; 988 } // foreach($rows as $row) 989 990 return $arr; 991 } 992 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Jul 28 15:48:31 2011 | Cross-referenced by PHPXref 0.7 |