[Solar-svn] Revision 2763
pmjones at solarphp.com
pmjones at solarphp.com
Thu Sep 20 13:23:45 CDT 2007
branch: Model and Record changes
Solar_Sql_Model
---------------
* [CHG] Methods insert(), update(), and delete() now accept a Record object
instead of only an array, and work just as with insertRecord() et al. from
previous versions.
* [CHG] Methods insert() and update(), when a Record object is passed in, now
call the filter() method on that Record.
Solar_Sql_Model_Record
----------------------
* [CHG] Method load() now completely overrides the parent method. Put
unserializing back in, reordered internal logic a bit.
* [CHG] Methods _insert()/_update()/delete() internal logic is somewhat
modified to go with new Model code.
* [BRK] Renamed all validate() methods to filter() (_preFilter(), filter(), and
_postFilter()).
* [BRK] Methods _serializeCols() and _unserializeCols() are now public, and no
longer have the underscore prefix.
Modified: branches/orm/Solar/Sql/Model/Record.php
===================================================================
--- branches/orm/Solar/Sql/Model/Record.php 2007-09-20 18:13:11 UTC (rev 2762)
+++ branches/orm/Solar/Sql/Model/Record.php 2007-09-20 18:23:45 UTC (rev 2763)
@@ -240,6 +240,8 @@
*
* Also unserializes columns per the "serialize_cols" model property.
*
+ * This is a complete override from the parent load() method.
+ *
* @param array|Solar_Struct $spec The data to load into the object.
*
* @param array $cols Load only these columns.
@@ -249,29 +251,44 @@
*/
public function load($spec, $cols = null)
{
+ // force to array
+ if ($spec instanceof Solar_Struct) {
+ // we can do this because $spec is of the same class
+ $data = $spec->_data;
+ } elseif (is_array($spec)) {
+ $data = $spec;
+ } else {
+ $data = array();
+ }
+
// remove columns not in the whitelist
if (! empty($cols)) {
$cols = (array) $cols;
- foreach ($spec as $key => $val) {
+ foreach ($data as $key => $val) {
if (! in_array($key, $cols)) {
- unset($spec[$key]);
+ unset($data[$key]);
}
}
}
- // do the "real" load
- parent::load($spec);
-
- // pull out belongs_to/has_one related data
- foreach ($this->_data as $key => $val) {
+ // pull out belongs_to/has_one related data.
+ foreach ($data as $key => $val) {
// if the key has double-underscores, it's an eager-load record.
if (strpos($key, '__') !== false) {
list($rel_name, $rel_key) = explode('__', $key);
$this->_data[$rel_name][$rel_key] = $val;
- unset($this->_data[$key]);
+ unset($data[$key]);
}
}
+ // unserialize as needed, then add remaining "real" columns.
+ // it's not enough to just merge the data. although slower, we need
+ // to loop so that __set() is honored.
+ $this->_model->unserializeCols($data);
+ foreach ($data as $key => $val) {
+ $this->$key = $val;
+ }
+
// load related data as records and collections
foreach ($this->_model->related as $name => $opts) {
@@ -504,56 +521,32 @@
protected function _insert()
{
- // filter the data (sanitize and validate)
- $this->_preValidate();
- $this->validate();
- $this->_postValidate();
-
- // convert to array for the SQL command
- $data = $this->toArray();
-
- // attempt to insert the record, and catch SQL exceptions.
try {
- // pre-logic, insert, reload, status, post-logic
$this->_preInsert();
- $result = $this->_model->insert($data);
- $this->load($result);
+ $this->_model->insert($this);
$this->setStatus('inserted');
$this->_postInsert();
} catch (Solar_Sql_Adapter_Exception_QueryFailed $e) {
- // something went wrong at the database
+ // failed at at the database for some reason
$this->setStatus('invalid');
$this->setInvalid('*', $e->getInfo('pdo_text'));
+ throw $e;
}
}
protected function _update()
{
- // filter the data (sanitize and validate)
- $this->_preValidate();
- $this->validate();
- $this->_postValidate();
-
- // convert to array for the SQL command
- $data = $this->toArray();
-
- // remove primary-key column from the data and build a WHERE clause
- $primary = $this->_model->primary_col;
- unset($data[$primary]);
- $where = array("$primary = ?" => $this->$primary);
-
- // attempt the update logic
try {
- // pre-logic, insert, reload, status, post-logic
$this->_preUpdate();
- $result = $this->_model->update($data, $where);
- $this->load($result);
+ $where = null;
+ $this->_model->update($this, $where);
$this->setStatus('updated');
$this->_postUpdate();
} catch (Solar_Sql_Adapter_Exception_QueryFailed $e) {
- // something went wrong at the database
+ // failed at at the database for some reason
$this->setStatus('invalid');
$this->setInvalid('*', $e->getInfo('pdo_text'));
+ throw $e;
}
}
@@ -581,11 +574,11 @@
{
}
- protected function _preValidate()
+ protected function _preFilter()
{
}
- protected function _postValidate()
+ protected function _postFilter()
{
}
@@ -599,12 +592,8 @@
public function delete()
{
$this->_checkDeleted();
-
- $primary = $this->_model->primary_col;
- $where = array("$primary = ?" => $this->$primary);
-
$this->_preDelete();
- $this->_model->delete($where);
+ $this->_model->delete($this);
$this->_postDelete();
}
@@ -776,13 +765,15 @@
/**
*
- * Validate and sanitize the data.
+ * Filter the data.
*
- * @return bool
+ * @return void
*
*/
- public function validate()
+ public function filter()
{
+ $this->_preFilter();
+
// create a filter object based on the model's filter class
$filter = Solar::factory($this->_model->filter_class);
@@ -819,7 +810,8 @@
throw $this->_exception('ERR_INVALID', array($this->_invalid));
}
- return $valid;
+ // post-logic, and done
+ $this->_postFilter();
}
public function form($cols = null)
Modified: branches/orm/Solar/Sql/Model.php
===================================================================
--- branches/orm/Solar/Sql/Model.php 2007-09-20 18:13:11 UTC (rev 2762)
+++ branches/orm/Solar/Sql/Model.php 2007-09-20 18:23:45 UTC (rev 2763)
@@ -1601,72 +1601,89 @@
*
* Inserts one row to the model table.
*
- * While this method automatically sets some values, and handles
- * serializing of columns where requested, it *does not* validate the
- * data in any way.
+ * @param array|Solar_Sql_Model_Record $spec The row data to insert.
*
- * @param array|Solar_Struct $data The row data to insert.
+ * @return array The data as inserted, including auto-incremented values,
+ * auto-sequence values, created/updated/inherit values, etc.
*
- * @return array The data as inserted, including auto-increment value if
- * one is defined.
- *
*/
- public function insert($data)
+ public function insert($spec)
{
- // make sure we have an array
- if ($data instanceof Solar_Struct) {
- $data = $data->toArray();
- } else {
- $data = (array) $data;
+ if (! is_array($spec) && ! ($spec instanceof Solar_Sql_Model_Record)) {
+ throw $this->_exception('ERR_NOT_ARRAY_OR_RECORD');
}
- // remove non-existent table columns from the data
- foreach ($data as $key => $val) {
- if (empty($this->_table_cols[$key])) {
- unset($data[$key]);
- }
-
- // remove empty autoinc columns to soothe postgres, which won't
- // take explicit NULLs in SERIAL cols.
- if ($this->_table_cols[$key]['autoinc'] && empty($val)) {
- unset($data[$key]);
- }
- }
-
+ /**
+ * Force or auto-set special columns
+ */
// force the 'created' value if there is a 'created' column
$now = date('Y-m-d H:i:s');
$key = $this->_created_col;
if ($key) {
- $data[$key] = $now;
+ $spec[$key] = $now;
}
// force the 'updated' value if there is an 'updated' column (same as
// the 'created' timestamp)
$key = $this->_updated_col;
if ($key) {
- $data[$key] = $now;
+ $spec[$key] = $now;
}
// if inheritance is turned on, auto-set the inheritance value,
// if not already set.
$key = $this->_inherit_col;
- if ($key && $this->_inherit_model && empty($data[$key])) {
- $data[$key] = $this->_inherit_model;
+ if ($key && $this->_inherit_model && empty($spec[$key])) {
+ $spec[$key] = $this->_inherit_model;
}
// auto-set sequence values if needed
foreach ($this->_sequence_cols as $key => $val) {
- if (empty($data[$key])) {
+ if (empty($spec[$key])) {
// no value given for the key.
// add a new sequence value.
- $data[$key] = $this->_sql->nextSequence($val);
+ $spec[$key] = $this->_sql->nextSequence($val);
}
}
- // serialize cols and insert
- $this->_serializeCols($data);
+ /**
+ * Record filtering
+ */
+ if ($spec instanceof Solar_Sql_Model_Record) {
+ // apply record filters and convert to array
+ $spec->filter();
+ $data = $spec->toArray();
+ } else {
+ // already an array
+ $data = $spec;
+ }
+
+ /**
+ * Final prep, then insert
+ */
+ // remove non-existent table columns from the data
+ foreach ($data as $key => $val) {
+ if (empty($this->_table_cols[$key])) {
+ unset($data[$key]);
+ // not in the table, so no need to check for autoinc
+ continue;
+ }
+
+ // remove empty autoinc columns to soothe postgres, which won't
+ // take explicit NULLs in SERIAL cols.
+ if ($this->_table_cols[$key]['autoinc'] && empty($val)) {
+ unset($data[$key]);
+ }
+ }
+
+ // do the insert
+ $this->serializeCols($data);
$this->_sql->insert($this->_table_name, $data);
+ $this->unserializeCols($data);
+ /**
+ * Post-insert
+ */
// no exception thrown, so it must have worked.
// if there was an autoincrement column, set its value in the data.
foreach ($this->_table_cols as $key => $val) {
@@ -1677,8 +1694,12 @@
}
}
- // unserialize cols and return the data as inserted
- $this->_unserializeCols($data);
+ // reload the data into the record if needed
+ if ($spec instanceof Solar_Sql_Model_Record) {
+ $spec->load($data);
+ }
+
+ // return the data as inserted
return $data;
}
@@ -1686,62 +1707,87 @@
*
* Updates rows in the model table.
*
- * While this method automatically sets some values, and handles
- * serializing of columns where requested, it *does not* validate the
- * data in any way.
+ * @param array|Solar_Sql_Model_Record $spec The row data to insert.
*
- * @param array|Solar_Struct $data The row data to insert.
- *
* @param string|array $where The WHERE clause to identify which rows to
* update.
*
* @return array The data as updated.
*
*/
- public function update($data, $where)
+ public function update($spec, $where)
{
- // make sure we have an array
- if ($data instanceof Solar_Struct) {
- $data = $data->toArray();
- } else {
- $data = (array) $data;
+ if (! is_array($spec) && ! ($spec instanceof Solar_Sql_Model_Record)) {
+ throw $this->_exception('ERR_NOT_ARRAY_OR_RECORD');
}
- // remove non-existent table columns from the data
- foreach ($data as $key => $val) {
- if (empty($this->_table_cols[$key])) {
- unset($data[$key]);
- }
- }
-
+ /**
+ * Force or auto-set special columns
+ */
// force the 'updated' value
$key = $this->_updated_col;
if ($key) {
- $data[$key] = date('Y-m-d H:i:s');
+ $spec[$key] = date('Y-m-d H:i:s');
}
// if inheritance is turned on, auto-set the inheritance value,
// if not already set.
$key = $this->_inherit_col;
if ($key && $this->_inherit_model && empty($this->$key)) {
- $data[$key] = $this->_inherit_model;
+ $spec[$key] = $this->_inherit_model;
}
// auto-set sequences where keys exist and values are empty
foreach ($this->_sequence_cols as $key => $val) {
- if (array_key_exists($key, $data) && empty($data[$key])) {
+ // hack to to account for arrays *and* Record/Struct objects
+ $exists = array_key_exists($key, $spec) || isset($spec[$key]);
+ if ($exists && empty($spec[$key])) {
// key is present but no value is given.
// add a new sequence value.
- $data[$key] = $this->_sql->nextSequence($val);
+ $spec[$key] = $this->_sql->nextSequence($val);
}
}
- // serialize cols and do the update
- $this->_serializeCols($data);
+ /**
+ * Record filtering and WHERE clause
+ */
+ if ($spec instanceof Solar_Sql_Model_Record) {
+ // apply record filters and convert to array
+ $spec->filter();
+ $data = $spec->toArray();
+
+ // force the WHERE clause
+ $primary = $this->_primary_col;
+ $where = array("$primary = ?" => $data[$primary]);
+
+ // don't update the primary key
+ unset($data[$primary]);
+ } else {
+ // already an array
+ $data = $spec;
+ }
+
+ /**
+ * Final prep, then update
+ */
+ // remove non-existent table columns from the data
+ foreach ($data as $key => $val) {
+ if (empty($this->_table_cols[$key])) {
+ unset($data[$key]);
+ }
+ }
+
+ // perform the update
+ $this->serializeCols($data);
$this->_sql->update($this->_table_name, $data, $where);
+ $this->unserializeCols($data);
+ // reload the data into the record if needed
+ if ($spec instanceof Solar_Sql_Model_Record) {
+ $spec->load($data);
+ }
+
// unserialize cols and return the data as updated
- $this->_unserializeCols($data);
return $data;
}
@@ -1749,14 +1795,21 @@
*
* Deletes rows from the model table.
*
- * @param string|array $where The WHERE clause to identify which rows to
- * delete.
+ * @param string|array|Solar_Sql_Model_Record $spec The WHERE clause to
+ * identify which rows to delete, or a record to delete.
*
- * @return array The data as updated.
+ * @return void
*
*/
- public function delete($where)
+ public function delete($spec)
{
+ if ($spec instanceof Solar_Sql_Model_Record) {
+ $primary = $this->_primary_col;
+ $where = array("$primary = ?" => $spec->$primary);
+ } else {
+ $where = $spec;
+ }
+
return $this->_sql->delete($this->_table_name, $where);
}
@@ -1773,7 +1826,7 @@
* @return void
*
*/
- protected function _serializeCols(&$data)
+ public function serializeCols(&$data)
{
foreach ($this->_serialize_cols as $key) {
if (! empty($data[$key]) && $data[$key] !== null) {
@@ -1799,7 +1852,7 @@
* @return void
*
*/
- protected function _unserializeCols(&$data)
+ public function unserializeCols(&$data)
{
// unseralize columns as-needed
foreach ($this->_serialize_cols as $key) {
More information about the Solar-svn
mailing list