Browse Source

initial draft of saving related models.

tags/2.0.0-beta
Qiang Xue 12 years ago
parent
commit
ef8b092278
  1. 14
      framework/db/ActiveQuery.php
  2. 186
      framework/db/ActiveRecord.php
  3. 22
      framework/db/ActiveRelation.php

14
framework/db/ActiveQuery.php

@ -253,17 +253,9 @@ class ActiveQuery extends Query
$t = strtolower($name);
if (!isset($relations[$t])) {
$getter = 'get' . $name;
if (!method_exists($model, $getter)) {
throw new Exception("Unknown relation: $name");
}
$relation = $model->$getter();
if ($relation instanceof ActiveRelation) {
$relation->primaryModel = null;
$relations[$t] = $relation;
} else {
throw new Exception("Unknown relation: $name");
}
$relation = $model->getRelation($name);
$relation->primaryModel = null;
$relations[$t] = $relation;
} else {
$relation = $relations[$t];
}

186
framework/db/ActiveRecord.php

@ -13,6 +13,7 @@ namespace yii\db;
use yii\base\Model;
use yii\base\Event;
use yii\base\ModelEvent;
use yii\base\BadMethodException;
use yii\db\Exception;
use yii\db\Connection;
use yii\db\TableSchema;
@ -768,6 +769,7 @@ abstract class ActiveRecord extends Model
* Returns the primary key value.
* @param boolean $asArray whether to return the primary key value as an array. If true,
* the return value will be an array with column name as key and column value as value.
* Note that for composite primary keys, an array will always be returned regardless of this parameter value.
* @return mixed the primary key value. An array (column name=>column value) is returned if the primary key is composite.
* If primary key is not defined, null will be returned.
*/
@ -859,27 +861,185 @@ abstract class ActiveRecord extends Model
/**
* @param string $name
* @param ActiveRecord $model
* @throws Exception
*/
public function linkWith($name, $model)
public function link($name, $model, $extraAttributes = array())
{
$getter = 'get' . $name;
if (!method_exists($this, $getter)) {
throw new Exception('Unknown relation: ' . $name);
$relation = $this->getRelation($name);
if ($relation->via !== null) {
if (is_array($relation->via)) {
/** @var $viaQuery ActiveRelation */
list($viaName, $viaQuery) = $relation->via[1];
/** @var $viaClass ActiveRecord */
$viaClass = $viaQuery->modelClass;
$viaTable = $viaClass::tableName();
} else {
$viaQuery = $relation->via;
$viaTable = reset($relation->via->from);
}
$columns = array();
foreach ($viaQuery->link as $a => $b) {
$columns[$a] = $this->$b;
}
foreach ($relation->link as $a => $b) {
$columns[$b] = $model->$a;
}
foreach ($extraAttributes as $k => $v) {
$columns[$k] = $v;
}
$command = $this->getDbConnection()->createCommand();
$command->insert($viaTable, $columns)->execute();
return;
// todo: update $viaName
}
$keys = $model->primaryKey();
$p1 = true;
foreach (array_keys($relation->link) as $key) {
if (!in_array($key, $keys, true)) {
$p1 = false;
break;
}
}
$relation = $this->$getter();
if (!$relation instanceof ActiveRelation) {
throw new Exception('Unknown relation: ' . $name);
$keys = $this->primaryKey();
$p2 = true;
foreach (array_values($relation->link) as $key) {
if (!in_array($key, $keys, true)) {
$p2 = false;
break;
}
}
if ($relation->multiple) {
if ($p1 && $p2) {
if ($this->getIsNewRecord() && $model->getIsNewRecord()) {
throw new Exception('both new');
} elseif ($this->getIsNewRecord()) {
foreach ($relation->link as $a => $b) {
$value = $model->$a;
if ($value === null) {
throw new Exception('key null');
}
$this->$b = $value;
}
$this->save(false);
} elseif ($model->getIsNewRecord()) {
foreach ($relation->link as $a => $b) {
$value = $this->$b;
if ($value === null) {
throw new Exception('key null');
}
$model->$a = $value;
}
$model->save(false);
} else {
throw new Exception('both old');
}
} elseif ($p1) {
foreach ($relation->link as $a => $b) {
$value = $model->$a;
if ($value === null) {
throw new Exception('key null');
}
$this->$b = $value;
}
$this->save(false);
} elseif ($p2) {
foreach ($relation->link as $a => $b) {
$key = $this->$b;
if ($key === null) {
$value = $this->$b;
if ($value === null) {
throw new Exception('key null');
}
$model->$a = $this->$b;
$model->$a = $value;
}
$model->save(false);
} else {
throw new Exception('');
}
// todo: update relation models
}
/**
* @param string $name
* @param ActiveRecord $model
* @throws Exception
*/
public function unlink($name, $model)
{
$relation = $this->getRelation($name);
if ($relation->via !== null) {
if (is_array($relation->via)) {
/** @var $viaQuery ActiveRelation */
$viaQuery = $relation->via[1];
/** @var $viaClass ActiveRecord */
$viaClass = $viaQuery->modelClass;
$viaTable = $viaClass::tableName();
} else {
$viaQuery = $relation->via;
$viaTable = reset($relation->via->from);
}
$columns = array();
foreach ($viaQuery->link as $a => $b) {
$columns[$a] = $this->$b;
}
foreach ($relation->link as $a => $b) {
$columns[$b] = $model->$a;
}
$command = $this->getDbConnection()->createCommand();
$command->delete($viaTable, $columns)->execute();
return;
}
$keys = $model->primaryKey();
$p1 = true;
foreach (array_keys($relation->link) as $key) {
if (!in_array($key, $keys, true)) {
$p1 = false;
break;
}
}
$keys = $this->primaryKey();
$p2 = true;
foreach (array_values($relation->link) as $key) {
if (!in_array($key, $keys, true)) {
$p2 = false;
break;
}
}
if ($p1 && $p2) {
foreach ($relation->link as $a => $b) {
$model->$a = null;
}
$model->save(false);
} elseif ($p1) {
foreach ($relation->link as $b) {
$this->$b = null;
}
$this->save(false);
} elseif ($p2) {
foreach ($relation->link as $a => $b) {
$model->$a = null;
}
$model->save(false);
} else {
throw new Exception('');
}
// todo: update relation models
}
/**
* @param string $name
* @return ActiveRelation
* @throws Exception
*/
public function getRelation($name)
{
$getter = 'get' . $name;
try {
$relation = $this->$getter();
if ($relation instanceof ActiveRelation) {
return $relation;
}
return $model->save(false);
} catch (BadMethodException $e) {
}
throw new Exception('Unknown relation: ' . $name);
}
}

22
framework/db/ActiveRelation.php

@ -12,7 +12,6 @@ namespace yii\db;
use yii\db\Connection;
use yii\db\Command;
use yii\db\QueryBuilder;
/**
* It is used in three scenarios:
@ -45,7 +44,7 @@ class ActiveRelation extends ActiveQuery
/**
* @var array|ActiveRelation
*/
protected $via;
public $via;
/**
* @param string $relationName
@ -55,19 +54,12 @@ class ActiveRelation extends ActiveQuery
*/
public function via($relationName, $callback = null)
{
$getter = 'get' . $relationName;
if (method_exists($this->primaryModel, $getter)) {
$relation = $this->primaryModel->$getter();
if ($relation instanceof ActiveRelation) {
$relation->primaryModel = null;
$this->via = array($relationName, $relation);
if ($callback !== null) {
call_user_func($callback, $relation);
}
return $this;
}
$relation = $this->primaryModel->getRelation($relationName);
$this->via = array($relationName, $relation);
if ($callback !== null) {
call_user_func($callback, $relation);
}
throw new Exception('Unknown relation: ' . $relationName);
return $this;
}
/**
@ -110,7 +102,6 @@ class ActiveRelation extends ActiveQuery
// via relation
/** @var $viaQuery ActiveRelation */
list($viaName, $viaQuery) = $this->via;
$viaQuery->primaryModel = $this->primaryModel;
if ($viaQuery->multiple) {
$viaModels = $viaQuery->all();
$this->primaryModel->populateRelation($viaName, $viaModels);
@ -143,6 +134,7 @@ class ActiveRelation extends ActiveQuery
// via relation
/** @var $viaQuery ActiveRelation */
list($viaName, $viaQuery) = $this->via;
$viaQuery->primaryModel = null;
$viaModels = $viaQuery->findWith($viaName, $primaryModels);
$this->filterByModels($viaModels);
} else {

Loading…
Cancel
Save