diff --git a/classes/automodeler/core.php b/classes/automodeler/core.php index c8ed8b1..8c7b041 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(); @@ -198,14 +201,20 @@ public function __set($key, $value) { if (array_key_exists($key, $this->_data)) { - $this->_data[$key] = $value; - $this->_validated = FALSE; + if($value !== $this->_data[$key]) + { + $this->_data[$key] = $value; + $this->_changed[$key] = true; + $this->_validated = FALSE; + } + return; } Log::instance()->add(Log::ERROR, 'Field '.$key.' does not exist in '.get_class($this).'!'); } + /** * sleep method for serialization * @@ -385,14 +394,21 @@ 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 { - $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); diff --git a/classes/automodeler/orm/core.php b/classes/automodeler/orm/core.php index d00d58a..ae5ed83 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(); @@ -28,18 +28,28 @@ 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 - { - $model = AutoModeler::factory($key); - $model->process_load($this->_lazy[$key]); - $model->process_load_state(); - return $model; - } + { + 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]); + $model->process_load_state(); + $this->_lazy[$key] = $model; + } + } - // Get the row from the foreign table - return AutoModeler::factory($key, $this->_data[$key.'_id']); + if(!isset($this->_lazy[$key])) + { + $this->_lazy[$key] = AutoModeler::factory($key, $this->_data[$key.'_id']); + } + + return $this->_lazy[$key]; } else if (isset($this->_data[$key])) return $this->_data[$key]; @@ -103,30 +113,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 @@ -135,7 +152,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; } @@ -152,33 +174,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); @@ -382,4 +398,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 +}