Commit 2cab70b0 by Carsten Brandt

Ensure consistent behavior in ActiveRecord::afterSave()

fixes #4012
parent cb87d7be
...@@ -395,7 +395,9 @@ class ActiveRecord extends BaseActiveRecord ...@@ -395,7 +395,9 @@ class ActiveRecord extends BaseActiveRecord
if ($runValidation && !$this->validate($attributes)) { if ($runValidation && !$this->validate($attributes)) {
return false; return false;
} }
if ($this->beforeSave(true)) { if (!$this->beforeSave(true)) {
return false;
}
$values = $this->getDirtyAttributes($attributes); $values = $this->getDirtyAttributes($attributes);
$response = static::getDb()->createCommand()->insert( $response = static::getDb()->createCommand()->insert(
...@@ -406,9 +408,6 @@ class ActiveRecord extends BaseActiveRecord ...@@ -406,9 +408,6 @@ class ActiveRecord extends BaseActiveRecord
$options $options
); );
// if (!isset($response['ok'])) {
// return false;
// }
$pk = static::primaryKey()[0]; $pk = static::primaryKey()[0];
$this->$pk = $response['_id']; $this->$pk = $response['_id'];
if ($pk != '_id') { if ($pk != '_id') {
...@@ -417,15 +416,12 @@ class ActiveRecord extends BaseActiveRecord ...@@ -417,15 +416,12 @@ class ActiveRecord extends BaseActiveRecord
$this->_version = $response['_version']; $this->_version = $response['_version'];
$this->_score = null; $this->_score = null;
$this->afterSave(true);
$this->setOldAttributes($values); $this->setOldAttributes($values);
$this->afterSave(true, $values);
return true; return true;
} }
return false;
}
/** /**
* Updates all records whos primary keys are given. * Updates all records whos primary keys are given.
* For example, to change the status to be 1 for all customers whose status is 2: * For example, to change the status to be 1 for all customers whose status is 2:
......
...@@ -224,8 +224,8 @@ abstract class ActiveRecord extends BaseActiveRecord ...@@ -224,8 +224,8 @@ abstract class ActiveRecord extends BaseActiveRecord
$this->setAttribute('_id', $newId); $this->setAttribute('_id', $newId);
$values['_id'] = $newId; $values['_id'] = $newId;
$this->afterSave(true);
$this->setOldAttributes($values); $this->setOldAttributes($values);
$this->afterSave(true, $values);
return true; return true;
} }
...@@ -241,7 +241,7 @@ abstract class ActiveRecord extends BaseActiveRecord ...@@ -241,7 +241,7 @@ abstract class ActiveRecord extends BaseActiveRecord
} }
$values = $this->getDirtyAttributes($attributes); $values = $this->getDirtyAttributes($attributes);
if (empty($values)) { if (empty($values)) {
$this->afterSave(false); $this->afterSave(false, $values);
return 0; return 0;
} }
$condition = $this->getOldPrimaryKey(true); $condition = $this->getOldPrimaryKey(true);
...@@ -260,10 +260,10 @@ abstract class ActiveRecord extends BaseActiveRecord ...@@ -260,10 +260,10 @@ abstract class ActiveRecord extends BaseActiveRecord
throw new StaleObjectException('The object being updated is outdated.'); throw new StaleObjectException('The object being updated is outdated.');
} }
$this->afterSave(false);
foreach ($values as $name => $value) { foreach ($values as $name => $value) {
$this->setOldAttribute($name, $this->getAttribute($name)); $this->setOldAttribute($name, $this->getAttribute($name));
} }
$this->afterSave(false, $values);
return $rows; return $rows;
} }
......
...@@ -127,8 +127,8 @@ abstract class ActiveRecord extends \yii\mongodb\ActiveRecord ...@@ -127,8 +127,8 @@ abstract class ActiveRecord extends \yii\mongodb\ActiveRecord
$this->setAttribute('_id', $newId); $this->setAttribute('_id', $newId);
$values['_id'] = $newId; $values['_id'] = $newId;
$this->afterSave(true);
$this->setOldAttributes($values); $this->setOldAttributes($values);
$this->afterSave(true, $values);
return true; return true;
} }
...@@ -144,7 +144,7 @@ abstract class ActiveRecord extends \yii\mongodb\ActiveRecord ...@@ -144,7 +144,7 @@ abstract class ActiveRecord extends \yii\mongodb\ActiveRecord
} }
$values = $this->getDirtyAttributes($attributes); $values = $this->getDirtyAttributes($attributes);
if (empty($values)) { if (empty($values)) {
$this->afterSave(false); $this->afterSave(false, $values);
return 0; return 0;
} }
...@@ -196,10 +196,10 @@ abstract class ActiveRecord extends \yii\mongodb\ActiveRecord ...@@ -196,10 +196,10 @@ abstract class ActiveRecord extends \yii\mongodb\ActiveRecord
} }
} }
$this->afterSave(false);
foreach ($values as $name => $value) { foreach ($values as $name => $value) {
$this->setOldAttribute($name, $this->getAttribute($name)); $this->setOldAttribute($name, $this->getAttribute($name));
} }
$this->afterSave(false, $values);
return $rows; return $rows;
} }
......
...@@ -99,11 +99,12 @@ class ActiveRecord extends BaseActiveRecord ...@@ -99,11 +99,12 @@ class ActiveRecord extends BaseActiveRecord
if ($runValidation && !$this->validate($attributes)) { if ($runValidation && !$this->validate($attributes)) {
return false; return false;
} }
if ($this->beforeSave(true)) { if (!$this->beforeSave(true)) {
return false;
}
$db = static::getDb(); $db = static::getDb();
$values = $this->getDirtyAttributes($attributes); $values = $this->getDirtyAttributes($attributes);
$pk = []; $pk = [];
// if ($values === []) {
foreach ($this->primaryKey() as $key) { foreach ($this->primaryKey() as $key) {
$pk[$key] = $values[$key] = $this->getAttribute($key); $pk[$key] = $values[$key] = $this->getAttribute($key);
if ($pk[$key] === null) { if ($pk[$key] === null) {
...@@ -111,7 +112,6 @@ class ActiveRecord extends BaseActiveRecord ...@@ -111,7 +112,6 @@ class ActiveRecord extends BaseActiveRecord
$this->setAttribute($key, $values[$key]); $this->setAttribute($key, $values[$key]);
} }
} }
// }
// save pk in a findall pool // save pk in a findall pool
$db->executeCommand('RPUSH', [static::keyPrefix(), static::buildKey($pk)]); $db->executeCommand('RPUSH', [static::keyPrefix(), static::buildKey($pk)]);
...@@ -124,15 +124,12 @@ class ActiveRecord extends BaseActiveRecord ...@@ -124,15 +124,12 @@ class ActiveRecord extends BaseActiveRecord
} }
$db->executeCommand('HMSET', $args); $db->executeCommand('HMSET', $args);
$this->afterSave(true);
$this->setOldAttributes($values); $this->setOldAttributes($values);
$this->afterSave(true, $values);
return true; return true;
} }
return false;
}
/** /**
* Updates the whole table using the provided attribute values and conditions. * Updates the whole table using the provided attribute values and conditions.
* For example, to change the status to be 1 for all customers whose status is 2: * For example, to change the status to be 1 for all customers whose status is 2:
......
...@@ -395,8 +395,8 @@ abstract class ActiveRecord extends BaseActiveRecord ...@@ -395,8 +395,8 @@ abstract class ActiveRecord extends BaseActiveRecord
return false; return false;
} }
$this->afterSave(true);
$this->setOldAttributes($values); $this->setOldAttributes($values);
$this->afterSave(true, $values);
return true; return true;
} }
...@@ -488,7 +488,7 @@ abstract class ActiveRecord extends BaseActiveRecord ...@@ -488,7 +488,7 @@ abstract class ActiveRecord extends BaseActiveRecord
} }
$values = $this->getDirtyAttributes($attributes); $values = $this->getDirtyAttributes($attributes);
if (empty($values)) { if (empty($values)) {
$this->afterSave(false); $this->afterSave(false, $values);
return 0; return 0;
} }
...@@ -530,10 +530,10 @@ abstract class ActiveRecord extends BaseActiveRecord ...@@ -530,10 +530,10 @@ abstract class ActiveRecord extends BaseActiveRecord
} }
} }
$this->afterSave(false);
foreach ($values as $name => $value) { foreach ($values as $name => $value) {
$this->setOldAttribute($name, $this->getAttribute($name)); $this->setOldAttribute($name, $this->getAttribute($name));
} }
$this->afterSave(false, $values);
return $rows; return $rows;
} }
......
...@@ -21,6 +21,7 @@ Yii Framework 2 Change Log ...@@ -21,6 +21,7 @@ Yii Framework 2 Change Log
- Bug #3194: Date formatter works only for timestamps in the year range 1970 to 2038 (kartik-v) - Bug #3194: Date formatter works only for timestamps in the year range 1970 to 2038 (kartik-v)
- Bug #3204: `yii\di\Container` did not handle the `$config` parameter well in case when it does not have a default value (qiangxue) - Bug #3204: `yii\di\Container` did not handle the `$config` parameter well in case when it does not have a default value (qiangxue)
- Bug #3216: Fixed the bug that `yii.activeForm.destroy()` did not remove `submit` event handlers (qiangxue) - Bug #3216: Fixed the bug that `yii.activeForm.destroy()` did not remove `submit` event handlers (qiangxue)
- Bug #3233: Ensure consistent behavior in ActiveRecord::afterSave() (cebe, qiangxue)
- Bug #3236: Return value for DateTime->format('U') casted to double to allow correct date formatting (pgaultier) - Bug #3236: Return value for DateTime->format('U') casted to double to allow correct date formatting (pgaultier)
- Bug #3268: Fixed the bug that the schema name in a table name was not respected by `yii\db\mysql\Schema` (terazoid, qiangxue) - Bug #3268: Fixed the bug that the schema name in a table name was not respected by `yii\db\mysql\Schema` (terazoid, qiangxue)
- Bug #3311: Fixed the bug that `yii\di\Container::has()` did not return correct value (mgrechanik, qiangxue) - Bug #3311: Fixed the bug that `yii\di\Container::has()` did not return correct value (mgrechanik, qiangxue)
......
...@@ -55,3 +55,7 @@ Upgrade from Yii 2.0 Beta ...@@ -55,3 +55,7 @@ Upgrade from Yii 2.0 Beta
This change is needed because `yii\web\View` no longer automatically generates CSRF meta tags due to issue #3358. This change is needed because `yii\web\View` no longer automatically generates CSRF meta tags due to issue #3358.
* If your model code is using the `file` validation rule, you should rename its `types` option to `extensions`. * If your model code is using the `file` validation rule, you should rename its `types` option to `extensions`.
* The behavior and signature of `ActiveRecord::afterSave()` has changed. `ActiveRecord::$isNewRecord` will now always be
false in afterSave and also dirty attributes are not available. This change has been made to have a more consistent and
expected behavior. The changed attributes are now available in the new parameter of afterSave() `$changedAttributes`.
\ No newline at end of file
...@@ -431,8 +431,8 @@ class ActiveRecord extends BaseActiveRecord ...@@ -431,8 +431,8 @@ class ActiveRecord extends BaseActiveRecord
} }
} }
$this->afterSave(true);
$this->setOldAttributes($values); $this->setOldAttributes($values);
$this->afterSave(true, $values);
return true; return true;
} }
......
...@@ -680,7 +680,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface ...@@ -680,7 +680,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
} }
$values = $this->getDirtyAttributes($attributes); $values = $this->getDirtyAttributes($attributes);
if (empty($values)) { if (empty($values)) {
$this->afterSave(false); $this->afterSave(false, $values);
return 0; return 0;
} }
$condition = $this->getOldPrimaryKey(true); $condition = $this->getOldPrimaryKey(true);
...@@ -699,10 +699,10 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface ...@@ -699,10 +699,10 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
throw new StaleObjectException('The object being updated is outdated.'); throw new StaleObjectException('The object being updated is outdated.');
} }
$this->afterSave(false);
foreach ($values as $name => $value) { foreach ($values as $name => $value) {
$this->_oldAttributes[$name] = $this->_attributes[$name]; $this->_oldAttributes[$name] = $this->_attributes[$name];
} }
$this->afterSave(false, $values);
return $rows; return $rows;
} }
...@@ -859,11 +859,14 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface ...@@ -859,11 +859,14 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
* When overriding this method, make sure you call the parent implementation so that * When overriding this method, make sure you call the parent implementation so that
* the event is triggered. * the event is triggered.
* @param boolean $insert whether this method called while inserting a record. * @param boolean $insert whether this method called while inserting a record.
* @param array $changedAttributes the attribute values that have changed during save.
* If false, it means the method is called while updating a record. * If false, it means the method is called while updating a record.
*/ */
public function afterSave($insert) public function afterSave($insert, $changedAttributes)
{ {
$this->trigger($insert ? self::EVENT_AFTER_INSERT : self::EVENT_AFTER_UPDATE); $this->trigger($insert ? self::EVENT_AFTER_INSERT : self::EVENT_AFTER_UPDATE, new ModelEvent([
'data' => ['changedAttributes' => $changedAttributes]
]));
} }
/** /**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment