mirror of
https://gitee.com/fastadminnet/framework.git
synced 2026-07-09 16:12:49 +08:00
多态关联支持预载入查询
This commit is contained in:
@@ -1377,7 +1377,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
$model = $this->parseModel($model);
|
$model = $this->parseModel($model);
|
||||||
$type = $type ?: Loader::parseName($this->name);
|
$type = $type ?: Loader::parseName($this->name);
|
||||||
if (is_array($morph)) {
|
if (is_array($morph)) {
|
||||||
list($foreignKey, $morphType) = $morph;
|
list($morphType, $foreignKey) = $morph;
|
||||||
} else {
|
} else {
|
||||||
$morphType = $morph . '_type';
|
$morphType = $morph . '_type';
|
||||||
$foreignKey = $morph . '_id';
|
$foreignKey = $morph . '_id';
|
||||||
@@ -1400,7 +1400,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
}
|
}
|
||||||
// 记录当前关联信息
|
// 记录当前关联信息
|
||||||
if (is_array($morph)) {
|
if (is_array($morph)) {
|
||||||
list($foreignKey, $morphType) = $morph;
|
list($morphType, $foreignKey) = $morph;
|
||||||
} else {
|
} else {
|
||||||
$morphType = $morph . '_type';
|
$morphType = $morph . '_type';
|
||||||
$foreignKey = $morph . '_id';
|
$foreignKey = $morph . '_id';
|
||||||
|
|||||||
@@ -80,6 +80,26 @@ class Relation
|
|||||||
return $this->query;
|
return $this->query;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析模型的完整命名空间
|
||||||
|
* @access public
|
||||||
|
* @param string $model 模型名(或者完整类名)
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function parseModel($model)
|
||||||
|
{
|
||||||
|
if (isset($this->alias[$model])) {
|
||||||
|
$model = $this->alias[$model];
|
||||||
|
}
|
||||||
|
if (false === strpos($model, '\\')) {
|
||||||
|
$path = explode('\\', get_class($this->parent));
|
||||||
|
array_pop($path);
|
||||||
|
array_push($path, Loader::parseName($model, 1));
|
||||||
|
$model = implode('\\', $path);
|
||||||
|
}
|
||||||
|
return $model;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前关联信息
|
* 获取当前关联信息
|
||||||
* @access public
|
* @access public
|
||||||
@@ -108,6 +128,7 @@ class Relation
|
|||||||
$relation = $this->parent->$name();
|
$relation = $this->parent->$name();
|
||||||
$foreignKey = $this->foreignKey;
|
$foreignKey = $this->foreignKey;
|
||||||
$localKey = $this->localKey;
|
$localKey = $this->localKey;
|
||||||
|
$middle = $this->middle;
|
||||||
|
|
||||||
// 判断关联类型执行查询
|
// 判断关联类型执行查询
|
||||||
switch ($this->type) {
|
switch ($this->type) {
|
||||||
@@ -127,7 +148,7 @@ class Relation
|
|||||||
// 关联查询
|
// 关联查询
|
||||||
$pk = $this->parent->getPk();
|
$pk = $this->parent->getPk();
|
||||||
$condition['pivot.' . $localKey] = $this->parent->$pk;
|
$condition['pivot.' . $localKey] = $this->parent->$pk;
|
||||||
$result = $this->belongsToManyQuery($relation->getQuery(), $this->middle, $foreignKey, $localKey, $condition)->select();
|
$result = $this->belongsToManyQuery($relation->getQuery(), $middle, $foreignKey, $localKey, $condition)->select();
|
||||||
foreach ($result as $set) {
|
foreach ($result as $set) {
|
||||||
$pivot = [];
|
$pivot = [];
|
||||||
foreach ($set->getData() as $key => $val) {
|
foreach ($set->getData() as $key => $val) {
|
||||||
@@ -147,19 +168,9 @@ class Relation
|
|||||||
break;
|
break;
|
||||||
case self::MORPH_TO:
|
case self::MORPH_TO:
|
||||||
// 多态模型
|
// 多态模型
|
||||||
$model = $this->parent->{$this->middle};
|
$model = $this->parseModel($this->parent->$middle);
|
||||||
// 多态类型映射
|
|
||||||
if (isset($this->alias[$model])) {
|
|
||||||
$model = $this->alias[$model];
|
|
||||||
}
|
|
||||||
if (false === strpos($model, '\\')) {
|
|
||||||
$path = explode('\\', get_class($this->parent));
|
|
||||||
array_pop($path);
|
|
||||||
array_push($path, Loader::parseName($model, 1));
|
|
||||||
$model = implode('\\', $path);
|
|
||||||
}
|
|
||||||
// 主键数据
|
// 主键数据
|
||||||
$pk = $this->parent->{$this->foreignKey};
|
$pk = $this->parent->$foreignKey;
|
||||||
$result = (new $model)->find($pk);
|
$result = (new $model)->find($pk);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -197,6 +208,7 @@ class Relation
|
|||||||
// 获取关联信息
|
// 获取关联信息
|
||||||
$localKey = $this->localKey;
|
$localKey = $this->localKey;
|
||||||
$foreignKey = $this->foreignKey;
|
$foreignKey = $this->foreignKey;
|
||||||
|
$middle = $this->middle;
|
||||||
switch ($this->type) {
|
switch ($this->type) {
|
||||||
case self::HAS_ONE:
|
case self::HAS_ONE:
|
||||||
case self::BELONGS_TO:
|
case self::BELONGS_TO:
|
||||||
@@ -261,6 +273,64 @@ class Relation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case self::MORPH_MANY:
|
||||||
|
$range = [];
|
||||||
|
foreach ($resultSet as $result) {
|
||||||
|
$pk = $result->getPk();
|
||||||
|
// 获取关联外键列表
|
||||||
|
if (isset($result->$pk)) {
|
||||||
|
$range[] = $result->$pk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($range)) {
|
||||||
|
$this->where[$foreignKey] = ['in', $range];
|
||||||
|
$this->where[$localKey] = $middle;
|
||||||
|
$data = $this->eagerlyMorphToMany($model, [
|
||||||
|
$foreignKey => ['in', $range],
|
||||||
|
$localKey => $middle,
|
||||||
|
], $relation, $subRelation, $closure);
|
||||||
|
|
||||||
|
// 关联数据封装
|
||||||
|
foreach ($resultSet as $result) {
|
||||||
|
if (!isset($data[$result->$pk])) {
|
||||||
|
$data[$result->$pk] = [];
|
||||||
|
}
|
||||||
|
$result->setAttr($relation, $this->resultSetBuild($data[$result->$pk], $class));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case self::MORPH_TO:
|
||||||
|
$range = [];
|
||||||
|
foreach ($resultSet as $result) {
|
||||||
|
// 获取关联外键列表
|
||||||
|
if (!empty($result->$foreignKey)) {
|
||||||
|
$range[$result->$middle][] = $result->$foreignKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($range)) {
|
||||||
|
foreach ($range as $key => $val) {
|
||||||
|
// 多态类型映射
|
||||||
|
$model = $this->parseModel($key);
|
||||||
|
$obj = new $model;
|
||||||
|
$pk = $obj->getPk();
|
||||||
|
$list = $obj->all($val, $subRelation);
|
||||||
|
$data = [];
|
||||||
|
foreach ($list as $k => $vo) {
|
||||||
|
$data[$vo->$pk] = $vo;
|
||||||
|
}
|
||||||
|
foreach ($resultSet as $result) {
|
||||||
|
if ($key == $result->$middle) {
|
||||||
|
if (!isset($data[$result->$foreignKey])) {
|
||||||
|
$data[$result->$foreignKey] = [];
|
||||||
|
}
|
||||||
|
$result->setAttr($relation, $this->resultSetBuild($data[$result->$foreignKey], $class));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $resultSet;
|
return $resultSet;
|
||||||
@@ -304,6 +374,7 @@ class Relation
|
|||||||
$model = $this->parent->$relation();
|
$model = $this->parent->$relation();
|
||||||
$localKey = $this->localKey;
|
$localKey = $this->localKey;
|
||||||
$foreignKey = $this->foreignKey;
|
$foreignKey = $this->foreignKey;
|
||||||
|
$middle = $this->middle;
|
||||||
switch ($this->type) {
|
switch ($this->type) {
|
||||||
case self::HAS_ONE:
|
case self::HAS_ONE:
|
||||||
case self::BELONGS_TO:
|
case self::BELONGS_TO:
|
||||||
@@ -334,6 +405,18 @@ class Relation
|
|||||||
$result->setAttr($relation, $this->resultSetBuild($data[$pk], $class));
|
$result->setAttr($relation, $this->resultSetBuild($data[$pk], $class));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case self::MORPH_MANY:
|
||||||
|
$pk = $result->getPk();
|
||||||
|
if (isset($result->$pk)) {
|
||||||
|
$data = $this->eagerlyMorphToMany($model, [$foreignKey => $result->$pk, $localKey => $middle], $relation, $subRelation, $closure);
|
||||||
|
$result->setAttr($relation, $this->resultSetBuild($data[$result->$pk], $class));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case self::MORPH_TO:
|
||||||
|
// 多态类型映射
|
||||||
|
$model = $this->parseModel($result->{$this->middle});
|
||||||
|
$this->eagerlyMorphToOne($model, $relation, $result, $subRelation);
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -426,6 +509,51 @@ class Relation
|
|||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多态MorphTo 关联模型预查询
|
||||||
|
* @access public
|
||||||
|
* @param object $model 关联模型对象
|
||||||
|
* @param array $where 关联预查询条件
|
||||||
|
* @param string $relation 关联名
|
||||||
|
* @param string $subRelation 子关联
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function eagerlyMorphToOne($model, $relation, &$result, $subRelation = '')
|
||||||
|
{
|
||||||
|
// 预载入关联查询 支持嵌套预载入
|
||||||
|
$pk = $this->parent->{$this->foreignKey};
|
||||||
|
$data = (new $model)->with($subRelation)->find($pk);
|
||||||
|
if ($data) {
|
||||||
|
$data->isUpdate(true);
|
||||||
|
}
|
||||||
|
$result->setAttr($relation, $data ?: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多态一对多 关联模型预查询
|
||||||
|
* @access public
|
||||||
|
* @param object $model 关联模型对象
|
||||||
|
* @param array $where 关联预查询条件
|
||||||
|
* @param string $relation 关联名
|
||||||
|
* @param string $subRelation 子关联
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function eagerlyMorphToMany($model, $where, $relation, $subRelation = '', $closure = false)
|
||||||
|
{
|
||||||
|
// 预载入关联查询 支持嵌套预载入
|
||||||
|
if ($closure) {
|
||||||
|
call_user_func_array($closure, [ & $model]);
|
||||||
|
}
|
||||||
|
$list = $model->getQuery()->where($where)->with($subRelation)->select();
|
||||||
|
$foreignKey = $this->foreignKey;
|
||||||
|
// 组装模型数据
|
||||||
|
$data = [];
|
||||||
|
foreach ($list as $set) {
|
||||||
|
$data[$set->$foreignKey][] = $set;
|
||||||
|
}
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置当前关联定义的数据表别名
|
* 设置当前关联定义的数据表别名
|
||||||
* @access public
|
* @access public
|
||||||
@@ -782,12 +910,14 @@ class Relation
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = call_user_func_array([$this->query, $method], $args);
|
$result = call_user_func_array([$this->query, $method], $args);
|
||||||
if ($result instanceof \think\db\Query) {
|
if ($result instanceof \think\db\Query) {
|
||||||
$this->option = $result->getOptions();
|
$this->option = $result->getOptions();
|
||||||
return $this;
|
return $this;
|
||||||
} else {
|
} else {
|
||||||
$this->option = [];
|
$this->option = [];
|
||||||
|
$baseQuery = false;
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user