/[cvs]/nfo/php/libs/net.php.pear/DB/storage.php
ViewVC logotype

Contents of /nfo/php/libs/net.php.pear/DB/storage.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (show annotations)
Tue Oct 29 19:11:41 2002 UTC (21 years, 8 months ago) by cvsjoko
Branch: MAIN
CVS Tags: HEAD
+ new pear-libraries

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

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed