C:/lib/adodb/adodb-active-record.inc.php Quellcode

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




Korrekturen, Hinweise und Ergänzungen

Bitte scheuen Sie sich nicht und melden Sie, was auf dieser Seite sachlich falsch oder irreführend ist, was ergänzt werden sollte, was fehlt usw. Dazu bitte oben aus dem Menü Seite den Eintrag Support Forum wählen. Es ist eine kostenlose Anmeldung erforderlich, um Anmerkungen zu posten. Unpassende Postings, Spam usw. werden kommentarlos entfernt.