Re: DB_DataObject - update only if changed
| From: | Alan Knowles | Date: | Sat, 08 Mar 2003 11:24:55 +0000 |
| Subject: | Re: DB_DataObject - update only if changed | ||
| References: | 1 2 | Groups: | php.pear.general php.pear.general |
| Request: | Send a blank email to pear-general+get-4110@lists.php.net to get a copy of this message | ||
Thanks - I decided to overload the update() method -
to only update changed items :
$dataobject->get(132);
$original = $dataobject; // clone/copy it..
$dataobject->setFrom($_POST);
if ($dataobject->validate()) {
$dataobject->update($original);} // otherwise an error... as it was the simplest/ most flexible way to do it (eg. if you use methods other than just setFrom() it can still take advantage of it..) Is in CVS now -should come out with the next release sometime this week.. Regards Alan Geoff Hopson wrote:
Sure - here you go... Geoff in php file somewhere... define('DB_DATAOBJECT_DIRTY', 128); // dirty flag in class definition.../** * This is a merger between the setFrom and update methods, so that only the * attributes that have changed are actually updated, instead of the entire * attribute set. * * * @param array | object $from * @access public * @return boolean , true on success * @author Geoff Hopson <ghopson@mac.com> */function updateFrom(&$from) { $keys = $this->_get_keys(); $items = $this->_get_table(); if (!$items) { DB_DataObject::raiseError("updateFrom:Could not find table definition for {$this->__table}", DB_DATAOBJECT_ERROR_INVALIDCONFIG); return; } foreach ($items as $k => $v) { if (in_array($k,$keys)) { continue; // dont overwrite keys } if (!$k) { continue; // ignore empty keys!!! what } if (is_object($from) && @isset($from->$k)) { $this->$k = $from->$k; continue; } if (!@isset($from[$k])) { continue; } if (is_object($from[$k])) { continue; } if (is_array($from[$k])) { continue; } if ($this->$k != $from[$k]) { $this->$k = $from[$k]; $items[$k] = $v + DB_DATAOBJECT_DIRTY; } } // now do the update... $datasaved = 1; $settings = '';$this->_connect();$__DB = &$GLOBALS['_DB_DATAOBJECT']['CONNECTIONS'][$this->_database_dsn_md5];foreach($items as $k => $v) { if ($v & DB_DATAOBJECT_DIRTY) { if (!isset($this->$k)) { continue; } if ($settings) { $settings .= ', '; } /* special values ... at least null is handled...*/ if ($this->$k === null) { $settings .= "$k = NULL"; }if ($v & DB_DATAOBJECT_STR) { $settings .= $k .' = '. $__DB->quote($this->$k) . ' '; continue; } if (is_numeric($this->$k)) { $settings .= "$k = {$this->$k} "; continue; } // at present we only cast to integers // - V2 may store additional data about float/int $settings .= "$k = " . intval($this->$k) . ' '; } }//$this->_condition=""; // dont clear condition if (!$GLOBALS['_DB_DATAOBJECT_PRODUCTION']) { $this->debug("got keys as ".serialize($keys),3); } $this->_build_condition($items,$keys); // echo " $settings, $this->condition "; if ($settings && $this->_condition) { $r = $this->_query("UPDATE {$this->__table} SET {$settings} {$this->_condition} "); if (PEAR::isError($r)) { $this->raiseError($r); return false; } if ($r < 1) { DB_DataObject::raiseError('No Data Affected By update',DB_DATAOBJECT_ERROR_NOAFFECTEDROWS); return false; }$this->_clear_cache(); return true; } //DB_DataObject::raiseError("updateFrom: No Data specifed for query $settings , {$this->_condition}", DB_DATAOBJECT_ERROR_NODATA); return true; }On Thursday, March 6, 2003, at 10:16 am, Alan Knowles wrote:Geoff Hopson wrote:-- Geoff Hopson Objectology Ltd. http://www.objectology.co.uk/Hi, I have written a method called 'updateFrom', which is basically a merger between setFrom and updateFrom - I use the 'dirty' flag in the setFrom part and check the flag in the update part. Seems to work OK with my limited testing so far If anyone wants it, let me know - it's currently sitting in my subclass of DataObject so I don't corrupt the PEAR package.can you send me it - I'll probably put it in the distribution under docs - or see how it could be integrated.. Regards AlanThanks for the response, Geoff On Wednesday, March 5, 2003, at 02:05 pm, Alan Knowles wrote:-- Can you help out? Need Consulting Services or Know of a Job? http://www.akbkhome.comGeoff Hopson wrote:-- Geoff Hopson Objectology Ltd. http://www.objectology.co.uk/Hi, I'm playing around with the DB_DataObject stuff (very nice - thanks!), but have a requirement only to update columns that have been changed. Right now the update method seems to set all columns to the current attributes of the object. For example, I have a user object with username, password, name attributes. If I change only the name on a form, the update statement is update users set username='blah', password = 'blah', name = 'newblah' where usr_id = 6; I would like the statement to be: update users set name = 'newblah' where usr_id = 6; Basically, I would like something like setFrom to only set the attributes that have changed and to mark them as dirty somehow. First question: are there plans to do this Now on to my planned solution - all comments appreciated! In setFrom:I'd be tempted to add another method rather than overloading setFrom too much.. $object->get($someid); $copy = $object->__clone(); $object->setFrom($object); $object->unsetIdentical($copy); // new method??? $object->update(); if you simple unset the identical values (and ignore the keys) it shouldnt build the update with only the changed values... Regards Alan- test the new value against the old value - if different, set the old value to the new value AND - set the $items so that the value for the attribute (eg DB_DATAOBJECT_STR) is bitwise-ANDed with a new value DB_DATABASE_DIRTY (which I have set to be 128)in update():- rejig the query builder to test for the DB_DATABASE_DIRTY bit, and if the attribute is dirty, use it in the query I'm playing with this right now - I can post the code if and when I get it working, but just wanted to ensure that I wasn't doing something stoopid (PHP novice...I'm allowed some mistakes :-)Thanks for any input, Geoff -- Geoff Hopson Objectology Ltd. http://www.objectology.co.uk/