From 9f8230024f3fe1f6db6dec74f20957d5e6856bd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nichlas=20L=C3=B6fdahl?= Date: Mon, 9 May 2011 19:37:38 +0200 Subject: [PATCH 01/10] Only update changed data-fields when saving model --- classes/automodeler/core.php | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/classes/automodeler/core.php b/classes/automodeler/core.php index c8ed8b1..f41e9d5 100644 --- a/classes/automodeler/core.php +++ b/classes/automodeler/core.php @@ -17,6 +17,9 @@ class AutoModeler_Core extends Model_Database implements ArrayAccess // The database fields protected $_data = array(); + // Fields that have been updated + protected $_changed = array(); + // Validation rules in a 'field' => 'rules' array protected $_rules = array(); protected $_callbacks = array(); @@ -196,9 +199,10 @@ public function __get($key) */ public function __set($key, $value) { - if (array_key_exists($key, $this->_data)) + if (array_key_exists($key, $this->_data) && $value != $this->_data[$key]) { $this->_data[$key] = $value; + $this->_changed[$key] = true; $this->_validated = FALSE; return; } @@ -206,6 +210,7 @@ public function __set($key, $value) Log::instance()->add(Log::ERROR, 'Field '.$key.' does not exist in '.get_class($this).'!'); } + /** * sleep method for serialization * @@ -385,7 +390,13 @@ public function save($validation = NULL) { if ($this->state() == AutoModeler::STATE_LOADED) // Do an update { - return count(db::update($this->_table_name)->set(array_diff_assoc($this->_data, array('id' => $this->_data['id'])))->where('id', '=', $this->_data['id'])->execute($this->_db)); + if(count($this->_changed)) + { + $count = count(db::update($this->_table_name)->set(array_intersect_key($this->_data, $this->_changed))->where('id', '=', $this->_data['id'])->execute($this->_db)); + $this->_changed = array(); + } else $count = 0; + + return $count; } else // Do an insert { From 07116dd756a8a19184fc3cb641c11d47285a06a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nichlas=20L=C3=B6fdahl?= Date: Mon, 9 May 2011 19:50:57 +0200 Subject: [PATCH 02/10] Logical error --- classes/automodeler/core.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/classes/automodeler/core.php b/classes/automodeler/core.php index f41e9d5..22f697b 100644 --- a/classes/automodeler/core.php +++ b/classes/automodeler/core.php @@ -199,11 +199,15 @@ public function __get($key) */ public function __set($key, $value) { - if (array_key_exists($key, $this->_data) && $value != $this->_data[$key]) + if (array_key_exists($key, $this->_data)) { - $this->_data[$key] = $value; - $this->_changed[$key] = true; - $this->_validated = FALSE; + if($value != $this->_data[$key]) + { + $this->_data[$key] = $value; + $this->_changed[$key] = true; + $this->_validated = FALSE; + } + return; } From ef78726fc517cb9405c344823cfa5006579a6e65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nichlas=20L=C3=B6fdahl?= Date: Mon, 9 May 2011 22:50:45 +0200 Subject: [PATCH 03/10] != -> !== --- classes/automodeler/core.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/automodeler/core.php b/classes/automodeler/core.php index 22f697b..40c14e1 100644 --- a/classes/automodeler/core.php +++ b/classes/automodeler/core.php @@ -201,7 +201,7 @@ public function __set($key, $value) { if (array_key_exists($key, $this->_data)) { - if($value != $this->_data[$key]) + if($value !== $this->_data[$key]) { $this->_data[$key] = $value; $this->_changed[$key] = true; From d7e8a5b29e0064331d39d6527f194a2a661800c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nichlas=20L=C3=B6fdahl?= Date: Sat, 4 Jun 2011 00:32:01 +0200 Subject: [PATCH 04/10] Filter out NULL-values at INSERT so that the default column value is used --- classes/automodeler/core.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/classes/automodeler/core.php b/classes/automodeler/core.php index 40c14e1..8c7b041 100644 --- a/classes/automodeler/core.php +++ b/classes/automodeler/core.php @@ -404,10 +404,11 @@ public function save($validation = NULL) } else // Do an insert { - $columns = array_keys($this->_data); + $data = array_filter($this->_data, function ($e) { return !is_null($e); }); + $columns = array_keys($data); $id = db::insert($this->_table_name) ->columns($columns) - ->values($this->_data)->execute($this->_db); + ->values($data)->execute($this->_db); $this->state(AutoModeler::STATE_LOADED); From efbc8adc4062b23eb07feb6255d435bc6cb63f21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nichlas=20L=C3=B6fdahl?= Date: Sat, 4 Jun 2011 00:58:46 +0200 Subject: [PATCH 05/10] Only load related objects once from the lazydata, keep the instance object in $_lazy --- classes/automodeler/orm/core.php | 79 +++++++++++++++++++------------- 1 file changed, 46 insertions(+), 33 deletions(-) diff --git a/classes/automodeler/orm/core.php b/classes/automodeler/orm/core.php index d00d58a..db465e0 100644 --- a/classes/automodeler/orm/core.php +++ b/classes/automodeler/orm/core.php @@ -31,15 +31,21 @@ public function __get($key) if (isset($this->_data[$key.'_id'])) { if (isset($this->_lazy[$key])) // See if we've lazy loaded it - { - $model = AutoModeler::factory($key); - $model->process_load($this->_lazy[$key]); - $model->process_load_state(); - return $model; - } + { + if(!($this->_lazy[$key] instanceof AutoModeler_ORM)) + { + $model = AutoModeler::factory($key); + $model->process_load($this->_lazy[$key]); + $model->process_load_state(); + $this->_lazy[$key] = $model; + } + } + else + { + $this->_lazy[$key] = AutoModeler::factory($key, $this->_data[$key.'_id']); + } - // Get the row from the foreign table - return AutoModeler::factory($key, $this->_data[$key.'_id']); + return $this->_lazy[$key]; } else if (isset($this->_data[$key])) return $this->_data[$key]; @@ -103,30 +109,37 @@ public function __set($key, $value) * * @return null */ - protected function process_load($data) - { - $parsed_data = array(); - foreach ($data as $key => $value) - { - if (strpos($key, ':')) - { - list($table, $field) = explode(':', $key); - if ($table == $this->_table_name) - { - $parsed_data[$field] = $value; - } - elseif ($field) - { - $this->_lazy[inflector::singular($table)][$field] = $value; - } - } - else - { - $parsed_data[$key] = $value; - } - } - $this->_data = $parsed_data; - } + protected function process_load($data) + { + $parsed_data = array(); + $lazy_data = array(); + + foreach ($data as $key => $value) + { + if (strpos($key, ':')) + { + list($table, $field) = explode(':', $key); + if ($table == $this->_table_name) + { + $parsed_data[$field] = $value; + } + elseif ($field) + { + $lazy_data[inflector::singular($table)][$field] = $value; + } + } + else + { + $parsed_data[$key] = $value; + } + } + $this->_data = $parsed_data; + foreach($lazy_data as $table => $fields) + { + if(!is_null($fields['id'])) $this->_lazy[$table] = $fields; + } + + } /** * Loads a model with a different one @@ -382,4 +395,4 @@ public function remove_parent($key) { return db::delete(AutoModeler::factory(inflector::singular($key))->get_table_name().'_'.$this->_table_name)->where(inflector::singular($this->_table_name).'_id', '=', $this->id)->execute($this->_db); } -} \ No newline at end of file +} From df366fb82a638e0a7504ba9abb34db9514a77f43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nichlas=20L=C3=B6fdahl?= Date: Sat, 4 Jun 2011 01:08:31 +0200 Subject: [PATCH 06/10] Support for multiple with() --- classes/automodeler/orm/core.php | 39 ++++++++++++++++---------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/classes/automodeler/orm/core.php b/classes/automodeler/orm/core.php index db465e0..3b619bf 100644 --- a/classes/automodeler/orm/core.php +++ b/classes/automodeler/orm/core.php @@ -13,7 +13,7 @@ class AutoModeler_ORM_Core extends AutoModeler protected $_has_many = array(); protected $_belongs_to = array(); - protected $_load_with = NULL; + protected $_load_with = array(); // Model data to lazy load protected $_lazy = array(); @@ -148,7 +148,12 @@ protected function process_load($data) */ public function with($model) { - $this->_load_with = $model; + $this->_load_with = (array)$this->_load_with; + + if(!in_array($model, $this->_load_with)) + { + $this->_load_with = array_merge($this->_load_with, (array)$model); + } return $this; } @@ -165,33 +170,27 @@ public function load(Database_Query_Builder_Select $query = NULL, $limit = 1) $query = db::select_array(array_keys($this->_data)); } - if ($this->_load_with !== NULL) + $this->_load_with = (array)$this->_load_with; + if (count($this->_load_with)) { - if (is_array($this->_load_with)) - { - $model = current(array_keys($this->_load_with)); - $alias = current(array_values($this->_load_with)); - } - else - { - $model = $this->_load_with; - $alias = $this->_load_with; - } - $fields = array(); foreach ($this->fields() as $field) { $fields[] = array($field, str_replace($this->_table_name.'.', '', $field)); } - foreach (AutoModeler_ORM::factory($model)->fields() as $field) + foreach($this->_load_with as $k => $v) { - $fields[] = array($field, str_replace('.', ':', $field)); + $alias = $v; + $model = is_numeric($k)?$v:$k; + foreach (AutoModeler_ORM::factory($model)->fields() as $field) + { + $fields[] = array($field, str_replace('.', ':', $field)); + } + $join_model = Model::factory($model); + $join_table = $join_model->get_table_name(); + $query->join($join_table, 'LEFT')->on($join_table.'.id', '=', $this->_table_name.'.'.$alias.'_id'); } - $query->select_array($fields, TRUE); - $join_model = Model::factory($model); - $join_table = $join_model->get_table_name(); - $query->join($join_table)->on($join_table.'.id', '=', $this->_table_name.'.'.$alias.'_id'); } return parent::load($query, $limit); From 3cb4843767bfeb0be0e0f8a12a731cf9832cd934 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nichlas=20L=C3=B6fdahl?= Date: Wed, 6 Jul 2011 15:33:14 +0200 Subject: [PATCH 07/10] return empty model if foreign_key is null --- classes/automodeler/orm/core.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/classes/automodeler/orm/core.php b/classes/automodeler/orm/core.php index 3b619bf..d979d94 100644 --- a/classes/automodeler/orm/core.php +++ b/classes/automodeler/orm/core.php @@ -28,7 +28,8 @@ class AutoModeler_ORM_Core extends AutoModeler public function __get($key) { // See if we are requesting a foreign key - if (isset($this->_data[$key.'_id'])) + //if (isset($this->_data[$key.'_id'])) + if(array_key_exists($key.'_id', $this->_data)) { if (isset($this->_lazy[$key])) // See if we've lazy loaded it { From f604eac57fad1c1cb727e2a61329fd06165985f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nichlas=20L=C3=B6fdahl?= Date: Wed, 3 Aug 2011 13:06:23 +0200 Subject: [PATCH 08/10] unset lazy-data if changing id-key --- classes/automodeler/orm/core.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/classes/automodeler/orm/core.php b/classes/automodeler/orm/core.php index d979d94..781492b 100644 --- a/classes/automodeler/orm/core.php +++ b/classes/automodeler/orm/core.php @@ -101,6 +101,10 @@ public function __set($key, $value) } else { + if(array_key_exists($key.'_id', $this->_data) && isset($this->_lazy[$key]) && $value !== $this->_data[$key]) { + unset($this->_lazy[$key]); + } + parent::__set($key, $value); } } From a811340b692532fabf6d2542d640e7af1bbf85d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nichlas=20L=C3=B6fdahl?= Date: Thu, 26 Jan 2012 21:12:42 +0100 Subject: [PATCH 09/10] key=alias, value=model with _load_with --- classes/automodeler/orm/core.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/classes/automodeler/orm/core.php b/classes/automodeler/orm/core.php index 781492b..a1842ec 100644 --- a/classes/automodeler/orm/core.php +++ b/classes/automodeler/orm/core.php @@ -185,8 +185,8 @@ public function load(Database_Query_Builder_Select $query = NULL, $limit = 1) } foreach($this->_load_with as $k => $v) { - $alias = $v; - $model = is_numeric($k)?$v:$k; + $model = $v; + $alias = is_numeric($k)?$v:$k; foreach (AutoModeler_ORM::factory($model)->fields() as $field) { $fields[] = array($field, str_replace('.', ':', $field)); From 2d5ab1f6e70f38ccdb1b01ea96ac3c38f85e23c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nichlas=20L=C3=B6fdahl?= Date: Wed, 4 Apr 2012 16:45:49 +0200 Subject: [PATCH 10/10] invalidate lazy data if field-id is changed --- classes/automodeler/orm/core.php | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/classes/automodeler/orm/core.php b/classes/automodeler/orm/core.php index a1842ec..ae5ed83 100644 --- a/classes/automodeler/orm/core.php +++ b/classes/automodeler/orm/core.php @@ -33,7 +33,9 @@ public function __get($key) { if (isset($this->_lazy[$key])) // See if we've lazy loaded it { - if(!($this->_lazy[$key] instanceof AutoModeler_ORM)) + if($this->_lazy[$key]['id'] != $this->_data[$key.'_id']) + unset($this->_lazy[$key]); + else if(!($this->_lazy[$key] instanceof AutoModeler_ORM)) { $model = AutoModeler::factory($key); $model->process_load($this->_lazy[$key]); @@ -41,7 +43,8 @@ public function __get($key) $this->_lazy[$key] = $model; } } - else + + if(!isset($this->_lazy[$key])) { $this->_lazy[$key] = AutoModeler::factory($key, $this->_data[$key.'_id']); } @@ -101,10 +104,6 @@ public function __set($key, $value) } else { - if(array_key_exists($key.'_id', $this->_data) && isset($this->_lazy[$key]) && $value !== $this->_data[$key]) { - unset($this->_lazy[$key]); - } - parent::__set($key, $value); } } @@ -185,8 +184,8 @@ public function load(Database_Query_Builder_Select $query = NULL, $limit = 1) } foreach($this->_load_with as $k => $v) { - $model = $v; - $alias = is_numeric($k)?$v:$k; + $alias = $v; + $model = is_numeric($k)?$v:$k; foreach (AutoModeler_ORM::factory($model)->fields() as $field) { $fields[] = array($field, str_replace('.', ':', $field));