Browse Source

Fix a regression in Has One saving introduced by #33 fix.

tags/1.5.2
Alban Jubert 6 years ago
parent
commit
9f657bdb50
  1. 4
      CHANGELOG.md
  2. 41
      src/SaveRelationsBehavior.php
  3. 2
      tests/SaveRelationsBehaviorTest.php
  4. 3
      tests/models/User.php

4
CHANGELOG.md

@ -1,5 +1,9 @@
# Yii2 Active Record Save Relations Behavior Change Log # Yii2 Active Record Save Relations Behavior Change Log
## [1.5.2]
### Fixed
- Fix a regression in Has One saving introduced by #33 fix.
## [1.5.1] ## [1.5.1]
### Fixed ### Fixed
- Bug #33: Custom relation scenario was set too late and was preventing attributes from being correctly set (thx @phrakon) - Bug #33: Custom relation scenario was set too late and was preventing attributes from being correctly set (thx @phrakon)

41
src/SaveRelationsBehavior.php

@ -296,16 +296,7 @@ class SaveRelationsBehavior extends Behavior
// If relation is has_one, try to set related model attributes // If relation is has_one, try to set related model attributes
foreach ($this->_relations as $relationName) { foreach ($this->_relations as $relationName) {
if (array_key_exists($relationName, $this->_oldRelationValue)) { // Relation was not set, do nothing... if (array_key_exists($relationName, $this->_oldRelationValue)) { // Relation was not set, do nothing...
/** @var ActiveQuery $relation */ $this->_setRelationForeignKeys($relationName);
$relation = $model->getRelation($relationName);
if ($relation->multiple === false && !empty($model->{$relationName})) {
Yii::debug("Setting foreign keys for {$relationName}", __METHOD__);
foreach ($relation->link as $relatedAttribute => $modelAttribute) {
if ($model->{$modelAttribute} !== $model->{$relationName}->{$relatedAttribute}) {
$model->{$modelAttribute} = $model->{$relationName}->{$relatedAttribute};
}
}
}
} }
} }
} }
@ -384,9 +375,13 @@ class SaveRelationsBehavior extends Behavior
*/ */
private function _prepareHasOneRelation(BaseActiveRecord $model, $relationName, ModelEvent $event) private function _prepareHasOneRelation(BaseActiveRecord $model, $relationName, ModelEvent $event)
{ {
Yii::debug("_prepareHasOneRelation for {$relationName}", __METHOD__);
$relationModel = $model->{$relationName}; $relationModel = $model->{$relationName};
$this->validateRelationModel(self::prettyRelationName($relationName), $relationName, $model->{$relationName}); $this->validateRelationModel(self::prettyRelationName($relationName), $relationName, $model->{$relationName});
if ($relationModel->getIsNewRecord()) { $relation = $model->getRelation($relationName);
$p1 = $model->isPrimaryKey(array_keys($relation->link));
$p2 = $relationModel::isPrimaryKey(array_values($relation->link));
if ($relationModel->getIsNewRecord() && $p1 && !$p2) {
// Save Has one relation new record // Save Has one relation new record
if ($event->isValid && (count($model->dirtyAttributes) || $model->{$relationName}->isNewRecord)) { if ($event->isValid && (count($model->dirtyAttributes) || $model->{$relationName}->isNewRecord)) {
Yii::debug('Saving ' . self::prettyRelationName($relationName) . ' relation model', __METHOD__); Yii::debug('Saving ' . self::prettyRelationName($relationName) . ' relation model', __METHOD__);
@ -465,6 +460,29 @@ class SaveRelationsBehavior extends Behavior
} }
/** /**
* Set relation foreign keys that point to owner primary key
* @param $relationName
*/
protected function _setRelationForeignKeys($relationName)
{
/** @var BaseActiveRecord $owner */
$owner = $this->owner;
/** @var ActiveQuery $relation */
$relation = $owner->getRelation($relationName);
if ($relation->multiple === false && !empty($owner->{$relationName})) {
Yii::debug("Setting foreign keys for {$relationName}", __METHOD__);
foreach ($relation->link as $relatedAttribute => $modelAttribute) {
if ($owner->{$modelAttribute} !== $owner->{$relationName}->{$relatedAttribute}) {
if ($owner->{$relationName}->isNewRecord) {
$owner->{$relationName}->save();
}
$owner->{$modelAttribute} = $owner->{$relationName}->{$relatedAttribute};
}
}
}
}
/**
* Link the related models. * Link the related models.
* If the models have not been changed, nothing will be done. * If the models have not been changed, nothing will be done.
* Related records will be linked to the owner model using the BaseActiveRecord `link()` method. * Related records will be linked to the owner model using the BaseActiveRecord `link()` method.
@ -642,7 +660,6 @@ class SaveRelationsBehavior extends Behavior
{ {
/** @var BaseActiveRecord $owner */ /** @var BaseActiveRecord $owner */
$owner = $this->owner; $owner = $this->owner;
if ($this->_oldRelationValue[$relationName] !== $owner->{$relationName}) { if ($this->_oldRelationValue[$relationName] !== $owner->{$relationName}) {
if ($owner->{$relationName} instanceof BaseActiveRecord) { if ($owner->{$relationName} instanceof BaseActiveRecord) {
$owner->link($relationName, $owner->{$relationName}); $owner->link($relationName, $owner->{$relationName});

2
tests/SaveRelationsBehaviorTest.php

@ -689,7 +689,7 @@ class SaveRelationsBehaviorTest extends \PHPUnit_Framework_TestCase
$profile->loadRelations($data); $profile->loadRelations($data);
$this->assertEquals('Someone Else', $profile->user->username, "User name should be 'Someone Else'"); $this->assertEquals('Someone Else', $profile->user->username, "User name should be 'Someone Else'");
$this->assertTrue($profile->user->isNewRecord, "User should be a new record"); $this->assertTrue($profile->user->isNewRecord, "User should be a new record");
$profile->save(); $this->assertEquals(1, $profile->user_id);
$this->assertTrue($profile->save(), 'Profile could not be saved'); $this->assertTrue($profile->save(), 'Profile could not be saved');
$this->assertEquals('Someone Else', $profile->user->username, "User name should be 'Someone Else'"); $this->assertEquals('Someone Else', $profile->user->username, "User name should be 'Someone Else'");
} }

3
tests/models/User.php

@ -3,9 +3,12 @@
namespace tests\models; namespace tests\models;
use lhs\Yii2SaveRelationsBehavior\SaveRelationsBehavior; use lhs\Yii2SaveRelationsBehavior\SaveRelationsBehavior;
use lhs\Yii2SaveRelationsBehavior\SaveRelationsTrait;
class User extends \yii\db\ActiveRecord class User extends \yii\db\ActiveRecord
{ {
use SaveRelationsTrait;
/** /**
* @inheritdoc * @inheritdoc
*/ */

Loading…
Cancel
Save