public function link($name, $model, $extraColumns = [])
{
$relation = $this->getRelation($name);
if ($relation->via !== null) {
if ($this->getIsNewRecord() || $model->getIsNewRecord()) {
throw new InvalidCallException('Unable to link models: the models being linked cannot be newly created.');
}
if (is_array($relation->via)) {
/* @var $viaRelation ActiveQuery */
list($viaName, $viaRelation) = $relation->via;
$viaClass = $viaRelation->modelClass;
// unset $viaName so that it can be reloaded to reflect the change
unset($this->_related[$viaName]);
} else {
$viaRelation = $relation->via;
$viaTable = reset($relation->via->from);
}
$columns = [];
foreach ($viaRelation->link as $a => $b) {
$columns[$a] = $this->{$b};
}
foreach ($relation->link as $a => $b) {
$columns[$b] = $model->{$a};
}
foreach ($extraColumns as $k => $v) {
$columns[$k] = $v;
}
if (is_array($relation->via)) {
/* @var $viaClass ActiveRecordInterface */
/* @var $record ActiveRecordInterface */
$record = new $viaClass();
foreach ($columns as $column => $value) {
$record->{$column} = $value;
}
$record->insert(false);
} else {
/* @var $viaTable string */
static::getDb()->createCommand()->insert($viaTable, $columns)->execute();
}
} else {
$p1 = $model->isPrimaryKey(array_keys($relation->link));
$p2 = static::isPrimaryKey(array_values($relation->link));
if ($p1 && $p2) {
if ($this->getIsNewRecord() && $model->getIsNewRecord()) {
throw new InvalidCallException('Unable to link models: at most one model can be newly created.');
} elseif ($this->getIsNewRecord()) {
$this->bindModels(array_flip($relation->link), $this, $model);
} else {
$this->bindModels($relation->link, $model, $this);
}
} elseif ($p1) {
$this->bindModels(array_flip($relation->link), $this, $model);
} elseif ($p2) {
$this->bindModels($relation->link, $model, $this);
} else {
throw new InvalidCallException('Unable to link models: the link defining the relation does not involve any primary key.');
}
}
// update lazily loaded related objects
if (!$relation->multiple) {
$this->_related[$name] = $model;
} elseif (isset($this->_related[$name])) {
if ($relation->indexBy !== null) {
if ($relation->indexBy instanceof \Closure) {
$index = call_user_func($relation->indexBy, $model);
} else {
$index = $model->{$relation->indexBy};
}
$this->_related[$name][$index] = $model;
} else {
$this->_related[$name][] = $model;
}
}
}