[ Index ] |
|
Code source de SPIP Agora 1.4 |
1 <?php 2 /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */ 3 // +----------------------------------------------------------------------+ 4 // | PHP Version 4 | 5 // +----------------------------------------------------------------------+ 6 // | Copyright (c) 1997-2004 The PHP Group | 7 // +----------------------------------------------------------------------+ 8 // | This source file is subject to version 2.02 of the PHP license, | 9 // | that is bundled with this package in the file LICENSE, and is | 10 // | available at through the world-wide-web at | 11 // | http://www.php.net/license/2_02.txt. | 12 // | If you did not receive a copy of the PHP license and are unable to | 13 // | obtain it through the world-wide-web, please send a note to | 14 // | license@php.net so we can mail you a copy immediately. | 15 // +----------------------------------------------------------------------+ 16 // | Author: Stig Bakken <stig@php.net> | 17 // | Maintainer: Daniel Convissor <danielc@php.net> | 18 // +----------------------------------------------------------------------+ 19 // 20 // $Id: storage.php,v 1.17 2004/02/04 01:42:05 danielc Exp $ 21 22 require_once 'DB.php'; 23 24 /** 25 * Provides an object interface to a table row. 26 * 27 * It lets you add, delete and change rows using objects rather than SQL 28 * statements. 29 * 30 * @package DB 31 * @version $Id: storage.php,v 1.17 2004/02/04 01:42:05 danielc Exp $ 32 * @category Database 33 * @author Stig Bakken <stig@php.net> 34 */ 35 class DB_storage extends PEAR 36 { 37 // {{{ properties 38 39 /** the name of the table (or view, if the backend database supports 40 updates in views) we hold data from */ 41 var $_table = null; 42 43 /** which column(s) in the table contains primary keys, can be a 44 string for single-column primary keys, or an array of strings 45 for multiple-column primary keys */ 46 var $_keycolumn = null; 47 48 /** DB connection handle used for all transactions */ 49 var $_dbh = null; 50 51 /** an assoc with the names of database fields stored as properties 52 in this object */ 53 var $_properties = array(); 54 55 /** an assoc with the names of the properties in this object that 56 have been changed since they were fetched from the database */ 57 var $_changes = array(); 58 59 /** flag that decides if data in this object can be changed. 60 objects that don't have their table's key column in their 61 property lists will be flagged as read-only. */ 62 var $_readonly = false; 63 64 /** function or method that implements a validator for fields that 65 are set, this validator function returns true if the field is 66 valid, false if not */ 67 var $_validator = null; 68 69 // }}} 70 // {{{ constructor 71 72 /** 73 * Constructor 74 * 75 * @param $table string the name of the database table 76 * 77 * @param $keycolumn mixed string with name of key column, or array of 78 * strings if the table has a primary key of more than one column 79 * 80 * @param $dbh object database connection object 81 * 82 * @param $validator mixed function or method used to validate 83 * each new value, called with three parameters: the name of the 84 * field/column that is changing, a reference to the new value and 85 * a reference to this object 86 * 87 */ 88 function DB_storage($table, $keycolumn, &$dbh, $validator = null) 89 { 90 $this->PEAR('DB_Error'); 91 $this->_table = $table; 92 $this->_keycolumn = $keycolumn; 93 $this->_dbh = $dbh; 94 $this->_readonly = false; 95 $this->_validator = $validator; 96 } 97 98 // }}} 99 // {{{ _makeWhere() 100 101 /** 102 * Utility method to build a "WHERE" clause to locate ourselves in 103 * the table. 104 * 105 * XXX future improvement: use rowids? 106 * 107 * @access private 108 */ 109 function _makeWhere($keyval = null) 110 { 111 if (is_array($this->_keycolumn)) { 112 if ($keyval === null) { 113 for ($i = 0; $i < sizeof($this->_keycolumn); $i++) { 114 $keyval[] = $this->{$this->_keycolumn[$i]}; 115 } 116 } 117 $whereclause = ''; 118 for ($i = 0; $i < sizeof($this->_keycolumn); $i++) { 119 if ($i > 0) { 120 $whereclause .= ' AND '; 121 } 122 $whereclause .= $this->_keycolumn[$i]; 123 if (is_null($keyval[$i])) { 124 // there's not much point in having a NULL key, 125 // but we support it anyway 126 $whereclause .= ' IS NULL'; 127 } else { 128 $whereclause .= ' = ' . $this->_dbh->quote($keyval[$i]); 129 } 130 } 131 } else { 132 if ($keyval === null) { 133 $keyval = @$this->{$this->_keycolumn}; 134 } 135 $whereclause = $this->_keycolumn; 136 if (is_null($keyval)) { 137 // there's not much point in having a NULL key, 138 // but we support it anyway 139 $whereclause .= ' IS NULL'; 140 } else { 141 $whereclause .= ' = ' . $this->_dbh->quote($keyval); 142 } 143 } 144 return $whereclause; 145 } 146 147 // }}} 148 // {{{ setup() 149 150 /** 151 * Method used to initialize a DB_storage object from the 152 * configured table. 153 * 154 * @param $keyval mixed the key[s] of the row to fetch (string or array) 155 * 156 * @return int DB_OK on success, a DB error if not 157 */ 158 function setup($keyval) 159 { 160 $whereclause = $this->_makeWhere($keyval); 161 $query = 'SELECT * FROM ' . $this->_table . ' WHERE ' . $whereclause; 162 $sth = $this->_dbh->query($query); 163 if (DB::isError($sth)) { 164 return $sth; 165 } 166 $row = $sth->fetchRow(DB_FETCHMODE_ASSOC); 167 if (DB::isError($row)) { 168 return $row; 169 } 170 if (!$row) { 171 return $this->raiseError(null, DB_ERROR_NOT_FOUND, null, null, 172 $query, null, true); 173 } 174 foreach ($row as $key => $value) { 175 $this->_properties[$key] = true; 176 $this->$key = $value; 177 } 178 return DB_OK; 179 } 180 181 // }}} 182 // {{{ insert() 183 184 /** 185 * Create a new (empty) row in the configured table for this 186 * object. 187 */ 188 function insert($newpk) 189 { 190 if (is_array($this->_keycolumn)) { 191 $primarykey = $this->_keycolumn; 192 } else { 193 $primarykey = array($this->_keycolumn); 194 } 195 settype($newpk, "array"); 196 for ($i = 0; $i < sizeof($primarykey); $i++) { 197 $pkvals[] = $this->_dbh->quote($newpk[$i]); 198 } 199 200 $sth = $this->_dbh->query("INSERT INTO $this->_table (" . 201 implode(",", $primarykey) . ") VALUES(" . 202 implode(",", $pkvals) . ")"); 203 if (DB::isError($sth)) { 204 return $sth; 205 } 206 if (sizeof($newpk) == 1) { 207 $newpk = $newpk[0]; 208 } 209 $this->setup($newpk); 210 } 211 212 // }}} 213 // {{{ toString() 214 215 /** 216 * Output a simple description of this DB_storage object. 217 * @return string object description 218 */ 219 function toString() 220 { 221 $info = strtolower(get_class($this)); 222 $info .= " (table="; 223 $info .= $this->_table; 224 $info .= ", keycolumn="; 225 if (is_array($this->_keycolumn)) { 226 $info .= "(" . implode(",", $this->_keycolumn) . ")"; 227 } else { 228 $info .= $this->_keycolumn; 229 } 230 $info .= ", dbh="; 231 if (is_object($this->_dbh)) { 232 $info .= $this->_dbh->toString(); 233 } else { 234 $info .= "null"; 235 } 236 $info .= ")"; 237 if (sizeof($this->_properties)) { 238 $info .= " [loaded, key="; 239 $keyname = $this->_keycolumn; 240 if (is_array($keyname)) { 241 $info .= "("; 242 for ($i = 0; $i < sizeof($keyname); $i++) { 243 if ($i > 0) { 244 $info .= ","; 245 } 246 $info .= $this->$keyname[$i]; 247 } 248 $info .= ")"; 249 } else { 250 $info .= $this->$keyname; 251 } 252 $info .= "]"; 253 } 254 if (sizeof($this->_changes)) { 255 $info .= " [modified]"; 256 } 257 return $info; 258 } 259 260 // }}} 261 // {{{ dump() 262 263 /** 264 * Dump the contents of this object to "standard output". 265 */ 266 function dump() 267 { 268 foreach ($this->_properties as $prop => $foo) { 269 print "$prop = "; 270 print htmlentities($this->$prop); 271 print "<br />\n"; 272 } 273 } 274 275 // }}} 276 // {{{ &create() 277 278 /** 279 * Static method used to create new DB storage objects. 280 * @param $data assoc. array where the keys are the names 281 * of properties/columns 282 * @return object a new instance of DB_storage or a subclass of it 283 */ 284 function &create($table, &$data) 285 { 286 $classname = strtolower(get_class($this)); 287 $obj =& new $classname($table); 288 foreach ($data as $name => $value) { 289 $obj->_properties[$name] = true; 290 $obj->$name = &$value; 291 } 292 return $obj; 293 } 294 295 // }}} 296 // {{{ loadFromQuery() 297 298 /** 299 * Loads data into this object from the given query. If this 300 * object already contains table data, changes will be saved and 301 * the object re-initialized first. 302 * 303 * @param $query SQL query 304 * 305 * @param $params parameter list in case you want to use 306 * prepare/execute mode 307 * 308 * @return int DB_OK on success, DB_WARNING_READ_ONLY if the 309 * returned object is read-only (because the object's specified 310 * key column was not found among the columns returned by $query), 311 * or another DB error code in case of errors. 312 */ 313 // XXX commented out for now 314 /* 315 function loadFromQuery($query, $params = null) 316 { 317 if (sizeof($this->_properties)) { 318 if (sizeof($this->_changes)) { 319 $this->store(); 320 $this->_changes = array(); 321 } 322 $this->_properties = array(); 323 } 324 $rowdata = $this->_dbh->getRow($query, DB_FETCHMODE_ASSOC, $params); 325 if (DB::isError($rowdata)) { 326 return $rowdata; 327 } 328 reset($rowdata); 329 $found_keycolumn = false; 330 while (list($key, $value) = each($rowdata)) { 331 if ($key == $this->_keycolumn) { 332 $found_keycolumn = true; 333 } 334 $this->_properties[$key] = true; 335 $this->$key = &$value; 336 unset($value); // have to unset, or all properties will 337 // refer to the same value 338 } 339 if (!$found_keycolumn) { 340 $this->_readonly = true; 341 return DB_WARNING_READ_ONLY; 342 } 343 return DB_OK; 344 } 345 */ 346 347 // }}} 348 // {{{ set() 349 350 /** 351 * Modify an attriute value. 352 */ 353 function set($property, $newvalue) 354 { 355 // only change if $property is known and object is not 356 // read-only 357 if ($this->_readonly) { 358 return $this->raiseError(null, DB_WARNING_READ_ONLY, null, 359 null, null, null, true); 360 } 361 if (@isset($this->_properties[$property])) { 362 if (empty($this->_validator)) { 363 $valid = true; 364 } else { 365 $valid = @call_user_func($this->_validator, 366 $this->_table, 367 $property, 368 $newvalue, 369 $this->$property, 370 $this); 371 } 372 if ($valid) { 373 $this->$property = $newvalue; 374 if (empty($this->_changes[$property])) { 375 $this->_changes[$property] = 0; 376 } else { 377 $this->_changes[$property]++; 378 } 379 } else { 380 return $this->raiseError(null, DB_ERROR_INVALID, null, 381 null, "invalid field: $property", 382 null, true); 383 } 384 return true; 385 } 386 return $this->raiseError(null, DB_ERROR_NOSUCHFIELD, null, 387 null, "unknown field: $property", 388 null, true); 389 } 390 391 // }}} 392 // {{{ &get() 393 394 /** 395 * Fetch an attribute value. 396 * 397 * @param string attribute name 398 * 399 * @return attribute contents, or null if the attribute name is 400 * unknown 401 */ 402 function &get($property) 403 { 404 // only return if $property is known 405 if (isset($this->_properties[$property])) { 406 return $this->$property; 407 } 408 $tmp = null; 409 return $tmp; 410 } 411 412 // }}} 413 // {{{ _DB_storage() 414 415 /** 416 * Destructor, calls DB_storage::store() if there are changes 417 * that are to be kept. 418 */ 419 function _DB_storage() 420 { 421 if (sizeof($this->_changes)) { 422 $this->store(); 423 } 424 $this->_properties = array(); 425 $this->_changes = array(); 426 $this->_table = null; 427 } 428 429 // }}} 430 // {{{ store() 431 432 /** 433 * Stores changes to this object in the database. 434 * 435 * @return DB_OK or a DB error 436 */ 437 function store() 438 { 439 foreach ($this->_changes as $name => $foo) { 440 $params[] = &$this->$name; 441 $vars[] = $name . ' = ?'; 442 } 443 if ($vars) { 444 $query = 'UPDATE ' . $this->_table . ' SET ' . 445 implode(', ', $vars) . ' WHERE ' . 446 $this->_makeWhere(); 447 $stmt = $this->_dbh->prepare($query); 448 $res = $this->_dbh->execute($stmt, $params); 449 if (DB::isError($res)) { 450 return $res; 451 } 452 $this->_changes = array(); 453 } 454 return DB_OK; 455 } 456 457 // }}} 458 // {{{ remove() 459 460 /** 461 * Remove the row represented by this object from the database. 462 * 463 * @return mixed DB_OK or a DB error 464 */ 465 function remove() 466 { 467 if ($this->_readonly) { 468 return $this->raiseError(null, DB_WARNING_READ_ONLY, null, 469 null, null, null, true); 470 } 471 $query = 'DELETE FROM ' . $this->_table .' WHERE '. 472 $this->_makeWhere(); 473 $res = $this->_dbh->query($query); 474 if (DB::isError($res)) { 475 return $res; 476 } 477 foreach ($this->_properties as $prop => $foo) { 478 unset($this->$prop); 479 } 480 $this->_properties = array(); 481 $this->_changes = array(); 482 return DB_OK; 483 } 484 485 // }}} 486 } 487 488 /* 489 * Local variables: 490 * tab-width: 4 491 * c-basic-offset: 4 492 * End: 493 */ 494 495 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sat Feb 24 14:40:03 2007 | par Balluche grâce à PHPXref 0.7 |