Skip to content

Commit

Permalink
Implementation for feature la-haute-societe#15
Browse files Browse the repository at this point in the history
  • Loading branch information
sspat committed Jun 7, 2017
1 parent 2b3d61a commit e2043b5
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 2 deletions.
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,14 @@ class Project extends \yii\db\ActiveRecord
...
'saveRelations' => [
'class' => SaveRelationsBehavior::className(),
'relations' => ['users', 'company']
'relations' => ['users', 'company', 'tags'],
'junctionTableColumns' => [
'tags' => function ($model) {
return [
'order' => $model->order
];
}
]
],
];
}
Expand Down Expand Up @@ -88,6 +95,14 @@ class Project extends \yii\db\ActiveRecord
{
return $this->hasMany(User::className(), ['id' => 'user_id'])->via('ProjectUsers');
}

/**
* @return ActiveQuery
*/
public function getTags()
{
return $this->hasMany(Tag::className(), ['id' => 'tag_id'])->viaTable('ProjectTags', ['project_id' => 'id']);
}

}
```
Expand Down Expand Up @@ -129,6 +144,12 @@ Attributes of the related model will be massively assigned using the `load() met
> See the PHPUnit tests for more examples.
Populate additional junction table columns in a many-to-many relation
---------------------------------------------------------------------
In a many-to-many relation involving a junction table additional column values can be saved to the junction table for each model.
See the configuration section for examples.


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.
Expand Down
31 changes: 30 additions & 1 deletion src/SaveRelationsBehavior.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class SaveRelationsBehavior extends Behavior
{

public $relations = [];
public $junctionTableColumns = [];
private $_oldRelationValue = [];
private $_relationsSaveStarted = false;
private $_transaction;
Expand Down Expand Up @@ -320,7 +321,8 @@ public function afterSave()
return implode("-", $model->getPrimaryKey(true));
});
foreach ($addedPks as $key) {
$model->link($relationName, $actualModels[$key]);
$junctionTableColumns = $this->_getJunctionTableColumns($relationName, $actualModels[$key]);
$model->link($relationName, $actualModels[$key], $junctionTableColumns);
}
} else { // Has one relation
if ($this->_oldRelationValue[$relationName] !== $model->{$relationName}) {
Expand All @@ -344,6 +346,33 @@ public function afterSave()
}
}

/**
* Return array of columns to save to the junction table for a related model having a many-to-many relation.
* @param string $relationName
* @param BaseActiveRecord $model
* @return array
*/
private function _getJunctionTableColumns($relationName, $model)
{
$junctionTableColumns = [];

if (array_key_exists($relationName, $this->junctionTableColumns)) {
if (is_callable($this->junctionTableColumns[$relationName])) {
$junctionTableColumns = $this->junctionTableColumns[$relationName]($model);
} elseif (is_array($this->junctionTableColumns[$relationName])) {
$junctionTableColumns = $this->junctionTableColumns[$relationName];
}

if (!is_array($junctionTableColumns)) {
throw new RuntimeException(
'Junction table columns definiton must return an array, got '.gettype($junctionTableColumns)
);
}
}

return $junctionTableColumns;
}

/**
* Compute the difference between two set of records using primary keys "tokens"
* @param BaseActiveRecord[] $initialRelations
Expand Down

0 comments on commit e2043b5

Please sign in to comment.