diff --git a/src/ActiveRecord.php b/src/ActiveRecord.php index c720d94b2..1030076b6 100644 --- a/src/ActiveRecord.php +++ b/src/ActiveRecord.php @@ -25,6 +25,9 @@ */ abstract class ActiveRecord extends BaseActiveRecord { + + protected $unsetAttrs = []; + /** * Returns the Mongo connection used by this AR class. * By default, the "mongodb" application component is used as the Mongo connection. @@ -165,6 +168,28 @@ public function attributes() throw new InvalidConfigException('The attributes() method of mongodb ActiveRecord has to be implemented by child classes.'); } + public function __set($name, $value) + { + unset($this->unsetAttrs[$name]); + parent::__set($name,$value); + } + + public function unset() + { + foreach(func_get_args() as $attribute) { + if (!$this->hasAttribute($attribute)) { + throw new UnknownPropertyException('Unsetting unknown property: ' . get_class($this) . '::' . $attribute); + } + if ($this->getIsNewRecord()) { + unset($this->$attribute); + } + else { + $this->$attribute = null; + $this->unsetAttrs[$attribute] = ''; + } + } + } + /** * Inserts a row into the associated Mongo collection using the attribute values of this record. * @@ -253,7 +278,7 @@ protected function updateInternal($attributes = null) return false; } $values = $this->getDirtyAttributes($attributes); - if (empty($values)) { + if (empty($values) && empty($this->unsetAttrs)) { $this->afterSave(false, $values); return 0; } @@ -265,9 +290,25 @@ protected function updateInternal($attributes = null) } $condition[$lock] = $this->$lock; } + + $document = $values; + if (!empty($this->unsetAttrs)){ + foreach ($this->unsetAttrs as $attr => $_) { + unset($document[$attr],$values[$attr],$this->$attr); + } + if (empty($document)) { + $document = ['$unset' => $this->unsetAttrs]; + } else { + $document = [ + '$set' => $document, + '$unset' => $this->unsetAttrs, + ]; + } + $this->unsetAttrs = []; + } // We do not check the return value of update() because it's possible // that it doesn't change anything and thus returns 0. - $rows = static::getCollection()->update($condition, $values); + $rows = static::getCollection()->update($condition, $document); if ($lock !== null && !$rows) { throw new StaleObjectException('The object being updated is outdated.');