Fixes #16552: Added check in yii\db\ActiveQuery::prepare() to prevent populating already populated relation when another relation is requested with via

This commit is contained in:
drlibra
2018-09-10 01:44:10 +05:00
committed by Alexander Makarov
parent 633d6b93b8
commit 5ee7fabbf9
3 changed files with 21 additions and 8 deletions

View File

@ -49,6 +49,7 @@ Yii Framework 2 Change Log
- Enh #16603: Added `yii\mutex\FileMutex::$isWindows` for Windows file shares on Unix guest machines (brandonkelly)
- Bug #16666: Fixed `yii\helpers\ArrayHelper::merge` (rustamwin)
- Enh: `yii\helpers\UnsetArrayValue`, `yii\helpers\ReplaceArrayValue` object now can be restored after serialization using `var_export()` function (silvefire)
- Bug #16552: Added check in `yii\db\ActiveQuery::prepare()` to prevent populating already populated relation when another relation is requested with `via` (drlibra)
2.0.15.1 March 21, 2018
-----------------------

View File

@ -172,11 +172,19 @@ class ActiveQuery extends Query implements ActiveQueryInterface
/* @var $viaQuery ActiveQuery */
list($viaName, $viaQuery) = $this->via;
if ($viaQuery->multiple) {
$viaModels = $viaQuery->all();
$this->primaryModel->populateRelation($viaName, $viaModels);
if ($this->primaryModel->isRelationPopulated($viaName)) {
$viaModels = $this->primaryModel->$viaName;
} else {
$viaModels = $viaQuery->all();
$this->primaryModel->populateRelation($viaName, $viaModels);
}
} else {
$model = $viaQuery->one();
$this->primaryModel->populateRelation($viaName, $model);
if ($this->primaryModel->isRelationPopulated($viaName)) {
$model = $this->primaryModel->$viaName;
} else {
$model = $viaQuery->one();
$this->primaryModel->populateRelation($viaName, $model);
}
$viaModels = $model === null ? [] : [$model];
}
$this->filterByModels($viaModels);

View File

@ -223,7 +223,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
* 1. Create a column to store the version number of each row. The column type should be `BIGINT DEFAULT 0`.
* Override this method to return the name of this column.
* 2. Ensure the version value is submitted and loaded to your model before any update or delete.
* Or add [[\yii\behaviors\OptimisticLockBehavior|OptimisticLockBehavior]] to your model
* Or add [[\yii\behaviors\OptimisticLockBehavior|OptimisticLockBehavior]] to your model
* class in order to automate the process.
* 3. In the Web form that collects the user input, add a hidden field that stores
* the lock version of the recording being updated.
@ -1734,18 +1734,22 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
* Sets relation dependencies for a property
* @param string $name property name
* @param ActiveQueryInterface $relation relation instance
* @param string|null $viaRelationName intermediate relation
*/
private function setRelationDependencies($name, $relation)
private function setRelationDependencies($name, $relation, $viaRelationName = null)
{
if (empty($relation->via) && $relation->link) {
foreach ($relation->link as $attribute) {
$this->_relationsDependencies[$attribute][$name] = $name;
if ($viaRelationName !== null) {
$this->_relationsDependencies[$attribute][] = $viaRelationName;
}
}
} elseif ($relation->via instanceof ActiveQueryInterface) {
$this->setRelationDependencies($name, $relation->via);
} elseif (is_array($relation->via)) {
list(, $viaQuery) = $relation->via;
$this->setRelationDependencies($name, $viaQuery);
list($viaRelationName, $viaQuery) = $relation->via;
$this->setRelationDependencies($name, $viaQuery, $viaRelationName);
}
}
}