Browse Source

Fix #2 issue: hasMany() relations are correctly saved now

tags/1.0.2 1.0.2
Alban Jubert 9 years ago
parent
commit
c8cd72a7fa
  1. 6
      README.md
  2. 25
      src/SaveRelationsBehavior.php
  3. 1
      tests/SaveRelationsBehaviorTest.php

6
README.md

@ -131,5 +131,9 @@ Validation
----------
Every declared related models will be validated prior to be saved. If any validation fails, for each related model attribute in error, an error associated with the named relation will be added to the owner model.
For `hasMany()` relations, the index of the related model will be used to identifiy the associated error.
For `hasMany()` relations, the index of the related model will be used to identifiy the associated error message.
> **Tips :**
> For relations not involving a junction table by using the `via()` or `viaTable()` methods, you should remove the attributes pointing to the owner model to be able to pass the validations.

25
src/SaveRelationsBehavior.php

@ -196,14 +196,14 @@ class SaveRelationsBehavior extends Behavior
if ($relation->multiple === false) {
// Save Has one relation new record
$pettyRelationName = Inflector::camel2words($relationName, true);
$this->_saveModelRecord($model->{$relationName}, $event, $pettyRelationName,
$relationName);
$this->_saveModelRecord($model->{$relationName}, $event, $pettyRelationName, $relationName);
} else {
// Save Has many relations new records
/** @var ActiveRecord $relationModel */
foreach ($model->{$relationName} as $i => $relationModel) {
$pettyRelationName = Inflector::camel2words($relationName, true) . " #{$i}";
$this->_saveModelRecord($relationModel, $event, $pettyRelationName, $relationName);
$this->_validateRelationModel($pettyRelationName, $relationName, $relationModel,
$event);
}
}
}
@ -214,6 +214,7 @@ class SaveRelationsBehavior extends Behavior
}
} catch (Exception $e) {
$this->_transaction->rollBack(); // If anything goes wrong, transaction will be rolled back
$event->isValid = false; // Stop saving, something went wrong
return false;
}
return true;
@ -281,8 +282,24 @@ class SaveRelationsBehavior extends Behavior
Yii::trace("Linking {$relationName} relation", __METHOD__);
$relation = $model->getRelation($relationName);
if ($relation->multiple === true) { // Has many relation
// Process new relations
$existingRecords = [];
foreach ($model->{$relationName} as $relationModel) {
if ($relationModel->isNewRecord) {
if ($relation->via !== null) {
$relationModel->save(false);
}
$model->link($relationName, $relationModel);
} else {
$existingRecords[] = $relationModel;
}
if (count($relationModel->dirtyAttributes)) {
$relationModel->save(false);
}
}
// Process existing added and deleted relations
list($addedPks, $deletedPks) = $this->_computePkDiff($this->_oldRelationValue[$relationName],
$model->{$relationName});
$existingRecords);
// Deleted relations
$initialModels = ArrayHelper::index($this->_oldRelationValue[$relationName],
function (ActiveRecord $model) {

1
tests/SaveRelationsBehaviorTest.php

@ -320,6 +320,7 @@ class SaveRelationsBehaviorTest extends \PHPUnit_Framework_TestCase
$links[1]->link = "http://www.otherlink.com/";
$project->links = $links;
$this->assertTrue($project->save(), 'Project could not be saved');
$this->assertEquals(2, count($project->links), 'Project should have 2 links before save');
$this->assertEquals("http://www.otherlink.com/", $project->links[1]->link,
'Second link "Link" attribute should be "http://www.otherlink.com/"');
}

Loading…
Cancel
Save